server/hook.py
author Sylvain Thénault <sylvain.thenault@logilab.fr>
Wed, 27 Jan 2010 10:00:19 +0100
changeset 4394 b98fbca17e9e
parent 4341 2d2aa2526c56
child 4490 d45cde54d464
permissions -rw-r--r--
missing import
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
     1
"""Hooks management
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
     2
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
     3
This module defined the `Hook` class and registry and a set of abstract classes
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
     4
for operations.
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
     5
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
     6
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
     7
Hooks are called before / after any individual update of entities / relations
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
     8
in the repository and on special events such as server startup or shutdown.
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
     9
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    10
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    11
Operations may be registered by hooks during a transaction, which will  be
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    12
fired when the pool is commited or rollbacked.
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    13
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    14
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    15
Entity hooks (eg before_add_entity, after_add_entity, before_update_entity,
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    16
after_update_entity, before_delete_entity, after_delete_entity) all have an
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    17
`entity` attribute
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    18
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    19
Relation (eg before_add_relation, after_add_relation, before_delete_relation,
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    20
after_delete_relation) all have `eidfrom`, `rtype`, `eidto` attributes.
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    21
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    22
Server start/stop hooks (eg server_startup, server_shutdown) have a `repo`
2847
c2ee28f4d4b1 use ._cw instead of .cw_req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2840
diff changeset
    23
attribute, but *their `_cw` attribute is None*.
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    24
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    25
Backup/restore hooks (eg server_backup, server_restore) have a `repo` and a
2847
c2ee28f4d4b1 use ._cw instead of .cw_req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2840
diff changeset
    26
`timestamp` attributes, but *their `_cw` attribute is None*.
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    27
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    28
Session hooks (eg session_open, session_close) have no special attribute.
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    29
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    30
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    31
:organization: Logilab
4307
7fba9c34c88f update copyright
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4106
diff changeset
    32
:copyright: 2001-2010 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2.
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    33
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    34
:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    35
"""
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    36
__docformat__ = "restructuredtext en"
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    37
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    38
from warnings import warn
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    39
from logging import getLogger
3660
7b41a6ba7400 fix/prepare propagation hooks usage
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3659
diff changeset
    40
from itertools import chain
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    41
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    42
from logilab.common.decorators import classproperty
2855
1d9be3dffa94 [repo] more deprecation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2847
diff changeset
    43
from logilab.common.deprecation import deprecated
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    44
from logilab.common.logging_ext import set_log_methods
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    45
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    46
from cubicweb.cwvreg import CWRegistry, VRegistry
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    47
from cubicweb.selectors import (objectify_selector, lltrace, match_search_state,
4075
e710f4052bd6 use implements instead of entity_implements
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4025
diff changeset
    48
                                implements)
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    49
from cubicweb.appobject import AppObject
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    50
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    51
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    52
ENTITIES_HOOKS = set(('before_add_entity',    'after_add_entity',
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    53
                      'before_update_entity', 'after_update_entity',
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    54
                      'before_delete_entity', 'after_delete_entity'))
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    55
RELATIONS_HOOKS = set(('before_add_relation',   'after_add_relation' ,
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    56
                       'before_delete_relation','after_delete_relation'))
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    57
SYSTEM_HOOKS = set(('server_backup', 'server_restore',
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    58
                    'server_startup', 'server_shutdown',
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    59
                    'session_open', 'session_close'))
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    60
ALL_HOOKS = ENTITIES_HOOKS | RELATIONS_HOOKS | SYSTEM_HOOKS
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    61
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    62
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    63
class HooksRegistry(CWRegistry):
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    64
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    65
    def register(self, obj, **kwargs):
2840
06daf13195d4 [hooks] deprecates hookhelper module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2835
diff changeset
    66
        try:
06daf13195d4 [hooks] deprecates hookhelper module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2835
diff changeset
    67
            iter(obj.events)
3394
51a25bdd7bdc [hooks] fix check for .events attribute in hooks
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3195
diff changeset
    68
        except AttributeError:
51a25bdd7bdc [hooks] fix check for .events attribute in hooks
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3195
diff changeset
    69
            raise
2840
06daf13195d4 [hooks] deprecates hookhelper module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2835
diff changeset
    70
        except:
3415
ae884253edeb nicer error message
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3396
diff changeset
    71
            raise Exception('bad .events attribute %s on %s.%s' % (
ae884253edeb nicer error message
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3396
diff changeset
    72
                obj.events, obj.__module__, obj.__name__))
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    73
        for event in obj.events:
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    74
            if event not in ALL_HOOKS:
3415
ae884253edeb nicer error message
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3396
diff changeset
    75
                raise Exception('bad event %s on %s.%s' % (
ae884253edeb nicer error message
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3396
diff changeset
    76
                    event, obj.__module__, obj.__name__))
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    77
        super(HooksRegistry, self).register(obj, **kwargs)
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    78
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    79
    def call_hooks(self, event, req=None, **kwargs):
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    80
        kwargs['event'] = event
2847
c2ee28f4d4b1 use ._cw instead of .cw_req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2840
diff changeset
    81
        for hook in sorted(self.possible_objects(req, **kwargs), key=lambda x: x.order):
c2ee28f4d4b1 use ._cw instead of .cw_req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2840
diff changeset
    82
            if hook.enabled:
c2ee28f4d4b1 use ._cw instead of .cw_req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2840
diff changeset
    83
                hook()
c2ee28f4d4b1 use ._cw instead of .cw_req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2840
diff changeset
    84
            else:
4339
fe93b670343d some fixes so that deprecation warning are properly localized
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4307
diff changeset
    85
                warn('[3.6] %s: enabled is deprecated' % hook.__class__)
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    86
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    87
VRegistry.REGISTRY_FACTORY['hooks'] = HooksRegistry
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    88
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    89
4011
394f853bb653 [migration] write migration instructions for permissions handling on relation definition
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4008
diff changeset
    90
def entity_oldnewvalue(entity, attr):
394f853bb653 [migration] write migration instructions for permissions handling on relation definition
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4008
diff changeset
    91
    """returns the couple (old attr value, new attr value)
394f853bb653 [migration] write migration instructions for permissions handling on relation definition
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4008
diff changeset
    92
    NOTE: will only work in a before_update_entity hook
394f853bb653 [migration] write migration instructions for permissions handling on relation definition
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4008
diff changeset
    93
    """
394f853bb653 [migration] write migration instructions for permissions handling on relation definition
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4008
diff changeset
    94
    # get new value and remove from local dict to force a db query to
394f853bb653 [migration] write migration instructions for permissions handling on relation definition
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4008
diff changeset
    95
    # fetch old value
394f853bb653 [migration] write migration instructions for permissions handling on relation definition
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4008
diff changeset
    96
    newvalue = entity.pop(attr, None)
394f853bb653 [migration] write migration instructions for permissions handling on relation definition
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4008
diff changeset
    97
    oldvalue = getattr(entity, attr)
394f853bb653 [migration] write migration instructions for permissions handling on relation definition
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4008
diff changeset
    98
    if newvalue is not None:
394f853bb653 [migration] write migration instructions for permissions handling on relation definition
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4008
diff changeset
    99
        entity[attr] = newvalue
394f853bb653 [migration] write migration instructions for permissions handling on relation definition
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4008
diff changeset
   100
    return oldvalue, newvalue
394f853bb653 [migration] write migration instructions for permissions handling on relation definition
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4008
diff changeset
   101
394f853bb653 [migration] write migration instructions for permissions handling on relation definition
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4008
diff changeset
   102
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   103
# some hook specific selectors #################################################
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   104
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   105
@objectify_selector
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   106
@lltrace
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   107
def match_event(cls, req, **kwargs):
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   108
    if kwargs.get('event') in cls.events:
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   109
        return 1
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   110
    return 0
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   111
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   112
@objectify_selector
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   113
@lltrace
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   114
def enabled_category(cls, req, **kwargs):
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   115
    if req is None:
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   116
        # server startup / shutdown event
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   117
        config = kwargs['repo'].config
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   118
    else:
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   119
        config = req.vreg.config
4106
ea4e93f9b151 more advanced hooks control
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4104
diff changeset
   120
    return config.is_hook_activated(cls)
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   121
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   122
@objectify_selector
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   123
@lltrace
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   124
def regular_session(cls, req, **kwargs):
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   125
    if req is None or req.is_super_session:
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   126
        return 0
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   127
    return 1
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   128
3660
7b41a6ba7400 fix/prepare propagation hooks usage
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3659
diff changeset
   129
7b41a6ba7400 fix/prepare propagation hooks usage
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3659
diff changeset
   130
class rechain(object):
7b41a6ba7400 fix/prepare propagation hooks usage
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3659
diff changeset
   131
    def __init__(self, *iterators):
7b41a6ba7400 fix/prepare propagation hooks usage
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3659
diff changeset
   132
        self.iterators = iterators
7b41a6ba7400 fix/prepare propagation hooks usage
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3659
diff changeset
   133
    def __iter__(self):
7b41a6ba7400 fix/prepare propagation hooks usage
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3659
diff changeset
   134
        return iter(chain(*self.iterators))
7b41a6ba7400 fix/prepare propagation hooks usage
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3659
diff changeset
   135
7b41a6ba7400 fix/prepare propagation hooks usage
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3659
diff changeset
   136
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   137
class match_rtype(match_search_state):
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   138
    """accept if parameters specified as initializer arguments are specified
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   139
    in named arguments given to the selector
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   140
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   141
    :param *expected: parameters (eg `basestring`) which are expected to be
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   142
                      found in named arguments (kwargs)
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   143
    """
4341
2d2aa2526c56 match_rtype hook selector now accepts frometypes/toetypes optional arguments to match only given subject/object entity types
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4339
diff changeset
   144
    def __init__(self, *expected, **more):
3660
7b41a6ba7400 fix/prepare propagation hooks usage
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3659
diff changeset
   145
        self.expected = expected
4341
2d2aa2526c56 match_rtype hook selector now accepts frometypes/toetypes optional arguments to match only given subject/object entity types
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4339
diff changeset
   146
        self.frometypes = more.pop('frometypes', None)
2d2aa2526c56 match_rtype hook selector now accepts frometypes/toetypes optional arguments to match only given subject/object entity types
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4339
diff changeset
   147
        self.toetypes = more.pop('toetypes', None)
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   148
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   149
    @lltrace
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   150
    def __call__(self, cls, req, *args, **kwargs):
4341
2d2aa2526c56 match_rtype hook selector now accepts frometypes/toetypes optional arguments to match only given subject/object entity types
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4339
diff changeset
   151
        if kwargs.get('rtype') not in self.expected:
2d2aa2526c56 match_rtype hook selector now accepts frometypes/toetypes optional arguments to match only given subject/object entity types
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4339
diff changeset
   152
            return 0
2d2aa2526c56 match_rtype hook selector now accepts frometypes/toetypes optional arguments to match only given subject/object entity types
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4339
diff changeset
   153
        if self.frometypes is not None and \
2d2aa2526c56 match_rtype hook selector now accepts frometypes/toetypes optional arguments to match only given subject/object entity types
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4339
diff changeset
   154
               req.describe(kwargs['eidfrom'])[0] not in self.frometypes:
2d2aa2526c56 match_rtype hook selector now accepts frometypes/toetypes optional arguments to match only given subject/object entity types
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4339
diff changeset
   155
            return 0
2d2aa2526c56 match_rtype hook selector now accepts frometypes/toetypes optional arguments to match only given subject/object entity types
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4339
diff changeset
   156
        if self.toetypes is not None and \
2d2aa2526c56 match_rtype hook selector now accepts frometypes/toetypes optional arguments to match only given subject/object entity types
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4339
diff changeset
   157
               req.describe(kwargs['eidto'])[0] not in self.toetypes:
2d2aa2526c56 match_rtype hook selector now accepts frometypes/toetypes optional arguments to match only given subject/object entity types
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4339
diff changeset
   158
            return 0
2d2aa2526c56 match_rtype hook selector now accepts frometypes/toetypes optional arguments to match only given subject/object entity types
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4339
diff changeset
   159
        return 1
2d2aa2526c56 match_rtype hook selector now accepts frometypes/toetypes optional arguments to match only given subject/object entity types
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4339
diff changeset
   160
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   161
4086
9b96126e0b14 add hook selector
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4075
diff changeset
   162
class match_rtype_sets(match_search_state):
9b96126e0b14 add hook selector
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4075
diff changeset
   163
    """accept if parameters specified as initializer arguments are specified
9b96126e0b14 add hook selector
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4075
diff changeset
   164
    in named arguments given to the selector
9b96126e0b14 add hook selector
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4075
diff changeset
   165
    """
9b96126e0b14 add hook selector
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4075
diff changeset
   166
9b96126e0b14 add hook selector
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4075
diff changeset
   167
    def __init__(self, *expected):
9b96126e0b14 add hook selector
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4075
diff changeset
   168
        self.expected = expected
9b96126e0b14 add hook selector
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4075
diff changeset
   169
9b96126e0b14 add hook selector
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4075
diff changeset
   170
    @lltrace
9b96126e0b14 add hook selector
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4075
diff changeset
   171
    def __call__(self, cls, req, *args, **kwargs):
9b96126e0b14 add hook selector
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4075
diff changeset
   172
        for rel_set in self.expected:
9b96126e0b14 add hook selector
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4075
diff changeset
   173
            if kwargs.get('rtype') in rel_set:
9b96126e0b14 add hook selector
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4075
diff changeset
   174
                return 1
9b96126e0b14 add hook selector
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4075
diff changeset
   175
        return 0
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   176
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   177
# base class for hook ##########################################################
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   178
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   179
class Hook(AppObject):
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   180
    __registry__ = 'hooks'
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   181
    __select__ = match_event() & enabled_category()
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   182
    # set this in derivated classes
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   183
    events = None
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   184
    category = None
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   185
    order = 0
2855
1d9be3dffa94 [repo] more deprecation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2847
diff changeset
   186
    # XXX deprecated
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   187
    enabled = True
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   188
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   189
    @classproperty
3376
f5c69485381f [appobjects] use __regid__ instead of __id__, more explicit
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3195
diff changeset
   190
    def __regid__(cls):
3383
c6aff16e5aed nicer warnings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   191
        warn('[3.6] %s.%s: please specify an id for your hook'
c6aff16e5aed nicer warnings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   192
             % (cls.__module__, cls.__name__), DeprecationWarning)
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   193
        return str(id(cls))
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   194
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   195
    @classmethod
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   196
    def __registered__(cls, vreg):
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   197
        super(Hook, cls).__registered__(vreg)
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   198
        if getattr(cls, 'accepts', None):
3383
c6aff16e5aed nicer warnings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   199
            warn('[3.6] %s.%s: accepts is deprecated, define proper __select__'
c6aff16e5aed nicer warnings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   200
                 % (cls.__module__, cls.__name__), DeprecationWarning)
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   201
            rtypes = []
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   202
            for ertype in cls.accepts:
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   203
                if ertype.islower():
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   204
                    rtypes.append(ertype)
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   205
                else:
4075
e710f4052bd6 use implements instead of entity_implements
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4025
diff changeset
   206
                    cls.__select__ = cls.__select__ & implements(ertype)
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   207
            if rtypes:
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   208
                cls.__select__ = cls.__select__ & match_rtype(*rtypes)
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   209
        return cls
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   210
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   211
    known_args = set(('entity', 'rtype', 'eidfrom', 'eidto', 'repo', 'timestamp'))
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   212
    def __init__(self, req, event, **kwargs):
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   213
        for arg in self.known_args:
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   214
            if arg in kwargs:
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   215
                setattr(self, arg, kwargs.pop(arg))
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   216
        super(Hook, self).__init__(req, **kwargs)
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   217
        self.event = event
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   218
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   219
    def __call__(self):
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   220
        if hasattr(self, 'call'):
3383
c6aff16e5aed nicer warnings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   221
            cls = self.__class__
c6aff16e5aed nicer warnings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   222
            warn('[3.6] %s.%s: call is deprecated, implements __call__'
c6aff16e5aed nicer warnings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   223
                 % (cls.__module__, cls.__name__), DeprecationWarning)
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   224
            if self.event.endswith('_relation'):
2847
c2ee28f4d4b1 use ._cw instead of .cw_req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2840
diff changeset
   225
                self.call(self._cw, self.eidfrom, self.rtype, self.eidto)
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   226
            elif 'delete' in self.event:
2847
c2ee28f4d4b1 use ._cw instead of .cw_req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2840
diff changeset
   227
                self.call(self._cw, self.entity.eid)
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   228
            elif self.event.startswith('server_'):
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   229
                self.call(self.repo)
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   230
            elif self.event.startswith('session_'):
2847
c2ee28f4d4b1 use ._cw instead of .cw_req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2840
diff changeset
   231
                self.call(self._cw)
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   232
            else:
2847
c2ee28f4d4b1 use ._cw instead of .cw_req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2840
diff changeset
   233
                self.call(self._cw, self.entity)
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   234
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   235
set_log_methods(Hook, getLogger('cubicweb.hook'))
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   236
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   237
2968
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   238
# base classes for relation propagation ########################################
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   239
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   240
class PropagateSubjectRelationHook(Hook):
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   241
    """propagate permissions and nosy list when new entity are added"""
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   242
    events = ('after_add_relation',)
3660
7b41a6ba7400 fix/prepare propagation hooks usage
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3659
diff changeset
   243
2968
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   244
    # to set in concrete class
3660
7b41a6ba7400 fix/prepare propagation hooks usage
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3659
diff changeset
   245
    main_rtype = None
2968
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   246
    subject_relations = None
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   247
    object_relations = None
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   248
3659
993997b4b41d 3.6 update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3423
diff changeset
   249
    def __call__(self):
993997b4b41d 3.6 update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3423
diff changeset
   250
        for eid in (self.eidfrom, self.eidto):
993997b4b41d 3.6 update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3423
diff changeset
   251
            etype = self._cw.describe(eid)[0]
4104
7e478d7caf20 [mq]: small_api_changes_for_3.6
Arthur Lutz <arthur.lutz@logilab.fr>
parents: 4086
diff changeset
   252
            if not self._cw.vreg.schema.eschema(etype).has_subject_relation(self.main_rtype):
2968
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   253
                return
3659
993997b4b41d 3.6 update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3423
diff changeset
   254
        if self.rtype in self.subject_relations:
993997b4b41d 3.6 update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3423
diff changeset
   255
            meid, seid = self.eidfrom, self.eidto
2968
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   256
        else:
3659
993997b4b41d 3.6 update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3423
diff changeset
   257
            assert self.rtype in self.object_relations
993997b4b41d 3.6 update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3423
diff changeset
   258
            meid, seid = self.eidto, self.eidfrom
993997b4b41d 3.6 update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3423
diff changeset
   259
        self._cw.unsafe_execute(
3090
8184bec7414d backport 3.5
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3087
diff changeset
   260
            'SET E %s P WHERE X %s P, X eid %%(x)s, E eid %%(e)s, NOT E %s P'\
3659
993997b4b41d 3.6 update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3423
diff changeset
   261
            % (self.main_rtype, self.main_rtype, self.main_rtype),
3090
8184bec7414d backport 3.5
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3087
diff changeset
   262
            {'x': meid, 'e': seid}, ('x', 'e'))
2968
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   263
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   264
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   265
class PropagateSubjectRelationAddHook(Hook):
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   266
    """propagate on existing entities when a permission or nosy list is added"""
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   267
    events = ('after_add_relation',)
3660
7b41a6ba7400 fix/prepare propagation hooks usage
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3659
diff changeset
   268
2968
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   269
    # to set in concrete class
3659
993997b4b41d 3.6 update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3423
diff changeset
   270
    main_rtype = None
2968
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   271
    subject_relations = None
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   272
    object_relations = None
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   273
3659
993997b4b41d 3.6 update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3423
diff changeset
   274
    def __call__(self):
4104
7e478d7caf20 [mq]: small_api_changes_for_3.6
Arthur Lutz <arthur.lutz@logilab.fr>
parents: 4086
diff changeset
   275
        eschema = self._cw.vreg.schema.eschema(self._cw.describe(self.eidfrom)[0])
3659
993997b4b41d 3.6 update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3423
diff changeset
   276
        execute = self._cw.unsafe_execute
2968
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   277
        for rel in self.subject_relations:
3720
5376aaadd16b backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3660
diff changeset
   278
            if rel in eschema.subjrels:
3090
8184bec7414d backport 3.5
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3087
diff changeset
   279
                execute('SET R %s P WHERE X eid %%(x)s, P eid %%(p)s, '
3659
993997b4b41d 3.6 update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3423
diff changeset
   280
                        'X %s R, NOT R %s P' % (self.rtype, rel, self.rtype),
993997b4b41d 3.6 update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3423
diff changeset
   281
                        {'x': self.eidfrom, 'p': self.eidto}, 'x')
2968
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   282
        for rel in self.object_relations:
3720
5376aaadd16b backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3660
diff changeset
   283
            if rel in eschema.objrels:
3090
8184bec7414d backport 3.5
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3087
diff changeset
   284
                execute('SET R %s P WHERE X eid %%(x)s, P eid %%(p)s, '
3659
993997b4b41d 3.6 update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3423
diff changeset
   285
                        'R %s X, NOT R %s P' % (self.rtype, rel, self.rtype),
993997b4b41d 3.6 update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3423
diff changeset
   286
                        {'x': self.eidfrom, 'p': self.eidto}, 'x')
2968
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   287
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   288
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   289
class PropagateSubjectRelationDelHook(Hook):
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   290
    """propagate on existing entities when a permission is deleted"""
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   291
    events = ('after_delete_relation',)
3660
7b41a6ba7400 fix/prepare propagation hooks usage
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3659
diff changeset
   292
2968
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   293
    # to set in concrete class
3659
993997b4b41d 3.6 update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3423
diff changeset
   294
    main_rtype = None
2968
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   295
    subject_relations = None
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   296
    object_relations = None
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   297
3659
993997b4b41d 3.6 update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3423
diff changeset
   298
    def __call__(self):
4104
7e478d7caf20 [mq]: small_api_changes_for_3.6
Arthur Lutz <arthur.lutz@logilab.fr>
parents: 4086
diff changeset
   299
        eschema = self._cw.vreg.schema.eschema(self._cw.describe(self.eidfrom)[0])
3659
993997b4b41d 3.6 update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3423
diff changeset
   300
        execute = self._cw.unsafe_execute
2968
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   301
        for rel in self.subject_relations:
3720
5376aaadd16b backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3660
diff changeset
   302
            if rel in eschema.subjrels:
3090
8184bec7414d backport 3.5
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3087
diff changeset
   303
                execute('DELETE R %s P WHERE X eid %%(x)s, P eid %%(p)s, '
3659
993997b4b41d 3.6 update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3423
diff changeset
   304
                        'X %s R' % (self.rtype, rel),
993997b4b41d 3.6 update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3423
diff changeset
   305
                        {'x': self.eidfrom, 'p': self.eidto}, 'x')
2968
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   306
        for rel in self.object_relations:
3720
5376aaadd16b backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3660
diff changeset
   307
            if rel in eschema.objrels:
3090
8184bec7414d backport 3.5
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3087
diff changeset
   308
                execute('DELETE R %s P WHERE X eid %%(x)s, P eid %%(p)s, '
3659
993997b4b41d 3.6 update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3423
diff changeset
   309
                        'R %s X' % (self.rtype, rel),
993997b4b41d 3.6 update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3423
diff changeset
   310
                        {'x': self.eidfrom, 'p': self.eidto}, 'x')
2968
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   311
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   312
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   313
# abstract classes for operation ###############################################
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   314
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   315
class Operation(object):
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   316
    """an operation is triggered on connections pool events related to
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   317
    commit / rollback transations. Possible events are:
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   318
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   319
    precommit:
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   320
      the pool is preparing to commit. You shouldn't do anything things which
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   321
      has to be reverted if the commit fail at this point, but you can freely
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   322
      do any heavy computation or raise an exception if the commit can't go.
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   323
      You can add some new operation during this phase but their precommit
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   324
      event won't be triggered
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   325
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   326
    commit:
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   327
      the pool is preparing to commit. You should avoid to do to expensive
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   328
      stuff or something that may cause an exception in this event
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   329
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   330
    revertcommit:
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   331
      if an operation failed while commited, this event is triggered for
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   332
      all operations which had their commit event already to let them
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   333
      revert things (including the operation which made fail the commit)
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   334
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   335
    rollback:
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   336
      the transaction has been either rollbacked either
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   337
      * intentionaly
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   338
      * a precommit event failed, all operations are rollbacked
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   339
      * a commit event failed, all operations which are not been triggered for
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   340
        commit are rollbacked
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   341
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   342
    order of operations may be important, and is controlled according to:
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   343
    * operation's class
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   344
    """
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   345
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   346
    def __init__(self, session, **kwargs):
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   347
        self.session = session
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   348
        self.__dict__.update(kwargs)
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   349
        self.register(session)
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   350
        # execution information
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   351
        self.processed = None # 'precommit', 'commit'
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   352
        self.failed = False
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   353
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   354
    def register(self, session):
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   355
        session.add_operation(self, self.insert_index())
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   356
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   357
    def insert_index(self):
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   358
        """return the index of  the lastest instance which is not a
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   359
        LateOperation instance
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   360
        """
3720
5376aaadd16b backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3660
diff changeset
   361
        # faster by inspecting operation in reverse order for heavy transactions
5376aaadd16b backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3660
diff changeset
   362
        i = None
5376aaadd16b backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3660
diff changeset
   363
        for i, op in enumerate(reversed(self.session.pending_operations)):
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   364
            if isinstance(op, (LateOperation, SingleLastOperation)):
3720
5376aaadd16b backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3660
diff changeset
   365
                continue
5376aaadd16b backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3660
diff changeset
   366
            return -i or None
5376aaadd16b backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3660
diff changeset
   367
        if i is None:
5376aaadd16b backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3660
diff changeset
   368
            return None
5376aaadd16b backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3660
diff changeset
   369
        return -(i + 1)
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   370
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   371
    def handle_event(self, event):
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   372
        """delegate event handling to the opertaion"""
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   373
        getattr(self, event)()
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   374
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   375
    def precommit_event(self):
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   376
        """the observed connections pool is preparing a commit"""
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   377
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   378
    def revertprecommit_event(self):
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   379
        """an error went when pre-commiting this operation or a later one
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   380
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   381
        should revert pre-commit's changes but take care, they may have not
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   382
        been all considered if it's this operation which failed
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   383
        """
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   384
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   385
    def commit_event(self):
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   386
        """the observed connections pool is commiting"""
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   387
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   388
    def revertcommit_event(self):
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   389
        """an error went when commiting this operation or a later one
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   390
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   391
        should revert commit's changes but take care, they may have not
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   392
        been all considered if it's this operation which failed
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   393
        """
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   394
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   395
    def rollback_event(self):
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   396
        """the observed connections pool has been rollbacked
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   397
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   398
        do nothing by default, the operation will just be removed from the pool
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   399
        operation list
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   400
        """
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   401
3998
94cc7cad3d2d backport stable into default
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3720
diff changeset
   402
    def postcommit_event(self):
94cc7cad3d2d backport stable into default
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3720
diff changeset
   403
        """the observed connections pool has committed"""
94cc7cad3d2d backport stable into default
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3720
diff changeset
   404
2855
1d9be3dffa94 [repo] more deprecation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2847
diff changeset
   405
    @property
2968
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   406
    @deprecated('[3.6] use self.session.user')
2855
1d9be3dffa94 [repo] more deprecation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2847
diff changeset
   407
    def user(self):
1d9be3dffa94 [repo] more deprecation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2847
diff changeset
   408
        return self.session.user
1d9be3dffa94 [repo] more deprecation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2847
diff changeset
   409
1d9be3dffa94 [repo] more deprecation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2847
diff changeset
   410
    @property
2968
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   411
    @deprecated('[3.6] use self.session.repo')
2855
1d9be3dffa94 [repo] more deprecation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2847
diff changeset
   412
    def repo(self):
1d9be3dffa94 [repo] more deprecation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2847
diff changeset
   413
        return self.session.repo
1d9be3dffa94 [repo] more deprecation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2847
diff changeset
   414
1d9be3dffa94 [repo] more deprecation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2847
diff changeset
   415
    @property
2968
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   416
    @deprecated('[3.6] use self.session.vreg.schema')
2855
1d9be3dffa94 [repo] more deprecation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2847
diff changeset
   417
    def schema(self):
1d9be3dffa94 [repo] more deprecation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2847
diff changeset
   418
        return self.session.repo.schema
1d9be3dffa94 [repo] more deprecation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2847
diff changeset
   419
1d9be3dffa94 [repo] more deprecation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2847
diff changeset
   420
    @property
2968
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   421
    @deprecated('[3.6] use self.session.vreg.config')
2855
1d9be3dffa94 [repo] more deprecation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2847
diff changeset
   422
    def config(self):
1d9be3dffa94 [repo] more deprecation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2847
diff changeset
   423
        return self.session.repo.config
1d9be3dffa94 [repo] more deprecation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2847
diff changeset
   424
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   425
set_log_methods(Operation, getLogger('cubicweb.session'))
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   426
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   427
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   428
class LateOperation(Operation):
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   429
    """special operation which should be called after all possible (ie non late)
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   430
    operations
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   431
    """
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   432
    def insert_index(self):
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   433
        """return the index of  the lastest instance which is not a
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   434
        SingleLastOperation instance
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   435
        """
3720
5376aaadd16b backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3660
diff changeset
   436
        # faster by inspecting operation in reverse order for heavy transactions
5376aaadd16b backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3660
diff changeset
   437
        i = None
5376aaadd16b backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3660
diff changeset
   438
        for i, op in enumerate(reversed(self.session.pending_operations)):
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   439
            if isinstance(op, SingleLastOperation):
3720
5376aaadd16b backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3660
diff changeset
   440
                continue
5376aaadd16b backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3660
diff changeset
   441
            return -i or None
5376aaadd16b backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3660
diff changeset
   442
        if i is None:
5376aaadd16b backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3660
diff changeset
   443
            return None
5376aaadd16b backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3660
diff changeset
   444
        return -(i + 1)
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   445
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   446
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   447
class SingleOperation(Operation):
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   448
    """special operation which should be called once"""
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   449
    def register(self, session):
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   450
        """override register to handle cases where this operation has already
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   451
        been added
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   452
        """
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   453
        operations = session.pending_operations
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   454
        index = self.equivalent_index(operations)
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   455
        if index is not None:
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   456
            equivalent = operations.pop(index)
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   457
        else:
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   458
            equivalent = None
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   459
        session.add_operation(self, self.insert_index())
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   460
        return equivalent
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   461
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   462
    def equivalent_index(self, operations):
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   463
        """return the index of the equivalent operation if any"""
3720
5376aaadd16b backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3660
diff changeset
   464
        for i, op in enumerate(reversed(operations)):
5376aaadd16b backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3660
diff changeset
   465
            if op.__class__ is self.__class__:
5376aaadd16b backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3660
diff changeset
   466
                return -(i+1)
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   467
        return None
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   468
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   469
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   470
class SingleLastOperation(SingleOperation):
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   471
    """special operation which should be called once and after all other
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   472
    operations
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   473
    """
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   474
    def insert_index(self):
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   475
        return None
2840
06daf13195d4 [hooks] deprecates hookhelper module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2835
diff changeset
   476
06daf13195d4 [hooks] deprecates hookhelper module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2835
diff changeset
   477
06daf13195d4 [hooks] deprecates hookhelper module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2835
diff changeset
   478
class SendMailOp(SingleLastOperation):
06daf13195d4 [hooks] deprecates hookhelper module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2835
diff changeset
   479
    def __init__(self, session, msg=None, recipients=None, **kwargs):
06daf13195d4 [hooks] deprecates hookhelper module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2835
diff changeset
   480
        # may not specify msg yet, as
06daf13195d4 [hooks] deprecates hookhelper module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2835
diff changeset
   481
        # `cubicweb.sobjects.supervision.SupervisionMailOp`
06daf13195d4 [hooks] deprecates hookhelper module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2835
diff changeset
   482
        if msg is not None:
06daf13195d4 [hooks] deprecates hookhelper module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2835
diff changeset
   483
            assert recipients
06daf13195d4 [hooks] deprecates hookhelper module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2835
diff changeset
   484
            self.to_send = [(msg, recipients)]
06daf13195d4 [hooks] deprecates hookhelper module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2835
diff changeset
   485
        else:
06daf13195d4 [hooks] deprecates hookhelper module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2835
diff changeset
   486
            assert recipients is None
06daf13195d4 [hooks] deprecates hookhelper module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2835
diff changeset
   487
            self.to_send = []
06daf13195d4 [hooks] deprecates hookhelper module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2835
diff changeset
   488
        super(SendMailOp, self).__init__(session, **kwargs)
06daf13195d4 [hooks] deprecates hookhelper module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2835
diff changeset
   489
06daf13195d4 [hooks] deprecates hookhelper module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2835
diff changeset
   490
    def register(self, session):
06daf13195d4 [hooks] deprecates hookhelper module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2835
diff changeset
   491
        previous = super(SendMailOp, self).register(session)
06daf13195d4 [hooks] deprecates hookhelper module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2835
diff changeset
   492
        if previous:
06daf13195d4 [hooks] deprecates hookhelper module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2835
diff changeset
   493
            self.to_send = previous.to_send + self.to_send
06daf13195d4 [hooks] deprecates hookhelper module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2835
diff changeset
   494
06daf13195d4 [hooks] deprecates hookhelper module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2835
diff changeset
   495
    def commit_event(self):
3418
7b49fa7e942d [api] use _cw, cw_row, cw_col, cw_rset etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3396
diff changeset
   496
        self.session.repo.threaded_task(self.sendmails)
2840
06daf13195d4 [hooks] deprecates hookhelper module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2835
diff changeset
   497
06daf13195d4 [hooks] deprecates hookhelper module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2835
diff changeset
   498
    def sendmails(self):
3418
7b49fa7e942d [api] use _cw, cw_row, cw_col, cw_rset etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3396
diff changeset
   499
        self.session.vreg.config.sendmails(self.to_send)
2968
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   500
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   501
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   502
class RQLPrecommitOperation(Operation):
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   503
    def precommit_event(self):
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   504
        execute = self.session.unsafe_execute
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   505
        for rql in self.rqls:
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   506
            execute(*rql)