server/hook.py
author Sylvain Thénault <sylvain.thenault@logilab.fr>
Thu, 15 Apr 2010 16:46:43 +0200
branchstable
changeset 5287 6346f1fd0a50
parent 5220 42f854b6083d
child 5302 dfd147de06b2
child 5421 8167de96c523
permissions -rw-r--r--
[hook] backport bad .events fix from default
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
5019
72734c210836 [c-c] new server_maintenance hook, called on c-c shell / upgrade
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4845
diff changeset
    22
Server start/maintenance/stop hooks (eg server_startup, server_maintenance,
72734c210836 [c-c] new server_maintenance hook, called on c-c shell / upgrade
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4845
diff changeset
    23
server_shutdown) have a `repo` attribute, but *their `_cw` attribute is None*.
72734c210836 [c-c] new server_maintenance hook, called on c-c shell / upgrade
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4845
diff changeset
    24
The `server_startup` is called on regular startup, while `server_maintenance`
72734c210836 [c-c] new server_maintenance hook, called on c-c shell / upgrade
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4845
diff changeset
    25
is called on cubicweb-ctl upgrade or shell commands. `server_shutdown` is
72734c210836 [c-c] new server_maintenance hook, called on c-c shell / upgrade
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4845
diff changeset
    26
called anyway.
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
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
    29
`timestamp` attributes, but *their `_cw` attribute is None*.
2835
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
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
    32
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    33
:organization: Logilab
4307
7fba9c34c88f update copyright
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4106
diff changeset
    34
: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
    35
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    36
: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
    37
"""
4835
13b0b96d7982 [repo] enhanced security handling: deprecates unsafe_execute, in favor of explicit read/write security control using the `enabled_security` context manager. Also code executed on the repository side is now unsafe by default.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4834
diff changeset
    38
from __future__ import with_statement
13b0b96d7982 [repo] enhanced security handling: deprecates unsafe_execute, in favor of explicit read/write security control using the `enabled_security` context manager. Also code executed on the repository side is now unsafe by default.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4834
diff changeset
    39
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    40
__docformat__ = "restructuredtext en"
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 warnings import warn
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    43
from logging import getLogger
3660
7b41a6ba7400 fix/prepare propagation hooks usage
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3659
diff changeset
    44
from itertools import chain
2835
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 logilab.common.decorators import classproperty
2855
1d9be3dffa94 [repo] more deprecation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2847
diff changeset
    47
from logilab.common.deprecation import deprecated
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    48
from logilab.common.logging_ext import set_log_methods
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    49
5093
8d073d2e089d [optimization] improve massive write performance by optimizing hooks selection
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5072
diff changeset
    50
from cubicweb import RegistryNotFound
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    51
from cubicweb.cwvreg import CWRegistry, VRegistry
4699
8757fca2c308 [hooks] match_rtype and match_rtype_sets don't need to extend match_search_state
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4522
diff changeset
    52
from cubicweb.selectors import (objectify_selector, lltrace, ExpectedValueSelector,
4075
e710f4052bd6 use implements instead of entity_implements
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4025
diff changeset
    53
                                implements)
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    54
from cubicweb.appobject import AppObject
4835
13b0b96d7982 [repo] enhanced security handling: deprecates unsafe_execute, in favor of explicit read/write security control using the `enabled_security` context manager. Also code executed on the repository side is now unsafe by default.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4834
diff changeset
    55
from cubicweb.server.session import security_enabled
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    56
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    57
ENTITIES_HOOKS = set(('before_add_entity',    'after_add_entity',
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    58
                      'before_update_entity', 'after_update_entity',
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    59
                      'before_delete_entity', 'after_delete_entity'))
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    60
RELATIONS_HOOKS = set(('before_add_relation',   'after_add_relation' ,
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    61
                       'before_delete_relation','after_delete_relation'))
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    62
SYSTEM_HOOKS = set(('server_backup', 'server_restore',
5019
72734c210836 [c-c] new server_maintenance hook, called on c-c shell / upgrade
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4845
diff changeset
    63
                    'server_startup', 'server_maintenance', 'server_shutdown',
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    64
                    'session_open', 'session_close'))
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    65
ALL_HOOKS = ENTITIES_HOOKS | RELATIONS_HOOKS | SYSTEM_HOOKS
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    66
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    67
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    68
class HooksRegistry(CWRegistry):
5093
8d073d2e089d [optimization] improve massive write performance by optimizing hooks selection
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5072
diff changeset
    69
    def initialization_completed(self):
8d073d2e089d [optimization] improve massive write performance by optimizing hooks selection
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5072
diff changeset
    70
        for appobjects in self.values():
8d073d2e089d [optimization] improve massive write performance by optimizing hooks selection
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5072
diff changeset
    71
            for cls in appobjects:
8d073d2e089d [optimization] improve massive write performance by optimizing hooks selection
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5072
diff changeset
    72
                if not cls.enabled:
8d073d2e089d [optimization] improve massive write performance by optimizing hooks selection
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5072
diff changeset
    73
                    warn('[3.6] %s: enabled is deprecated' % cls)
8d073d2e089d [optimization] improve massive write performance by optimizing hooks selection
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5072
diff changeset
    74
                    self.unregister(cls)
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    75
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    76
    def register(self, obj, **kwargs):
5287
6346f1fd0a50 [hook] backport bad .events fix from default
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5220
diff changeset
    77
        obj.check_events()
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    78
        super(HooksRegistry, self).register(obj, **kwargs)
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    79
4835
13b0b96d7982 [repo] enhanced security handling: deprecates unsafe_execute, in favor of explicit read/write security control using the `enabled_security` context manager. Also code executed on the repository side is now unsafe by default.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4834
diff changeset
    80
    def call_hooks(self, event, session=None, **kwargs):
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    81
        kwargs['event'] = event
4835
13b0b96d7982 [repo] enhanced security handling: deprecates unsafe_execute, in favor of explicit read/write security control using the `enabled_security` context manager. Also code executed on the repository side is now unsafe by default.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4834
diff changeset
    82
        if session is None:
13b0b96d7982 [repo] enhanced security handling: deprecates unsafe_execute, in favor of explicit read/write security control using the `enabled_security` context manager. Also code executed on the repository side is now unsafe by default.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4834
diff changeset
    83
            for hook in sorted(self.possible_objects(session, **kwargs),
13b0b96d7982 [repo] enhanced security handling: deprecates unsafe_execute, in favor of explicit read/write security control using the `enabled_security` context manager. Also code executed on the repository side is now unsafe by default.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4834
diff changeset
    84
                               key=lambda x: x.order):
2847
c2ee28f4d4b1 use ._cw instead of .cw_req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2840
diff changeset
    85
                hook()
4835
13b0b96d7982 [repo] enhanced security handling: deprecates unsafe_execute, in favor of explicit read/write security control using the `enabled_security` context manager. Also code executed on the repository side is now unsafe by default.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4834
diff changeset
    86
        else:
13b0b96d7982 [repo] enhanced security handling: deprecates unsafe_execute, in favor of explicit read/write security control using the `enabled_security` context manager. Also code executed on the repository side is now unsafe by default.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4834
diff changeset
    87
            # by default, hooks are executed with security turned off
13b0b96d7982 [repo] enhanced security handling: deprecates unsafe_execute, in favor of explicit read/write security control using the `enabled_security` context manager. Also code executed on the repository side is now unsafe by default.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4834
diff changeset
    88
            with security_enabled(session, read=False):
13b0b96d7982 [repo] enhanced security handling: deprecates unsafe_execute, in favor of explicit read/write security control using the `enabled_security` context manager. Also code executed on the repository side is now unsafe by default.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4834
diff changeset
    89
                hooks = sorted(self.possible_objects(session, **kwargs),
13b0b96d7982 [repo] enhanced security handling: deprecates unsafe_execute, in favor of explicit read/write security control using the `enabled_security` context manager. Also code executed on the repository side is now unsafe by default.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4834
diff changeset
    90
                               key=lambda x: x.order)
13b0b96d7982 [repo] enhanced security handling: deprecates unsafe_execute, in favor of explicit read/write security control using the `enabled_security` context manager. Also code executed on the repository side is now unsafe by default.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4834
diff changeset
    91
                with security_enabled(session, write=False):
13b0b96d7982 [repo] enhanced security handling: deprecates unsafe_execute, in favor of explicit read/write security control using the `enabled_security` context manager. Also code executed on the repository side is now unsafe by default.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4834
diff changeset
    92
                    for hook in hooks:
13b0b96d7982 [repo] enhanced security handling: deprecates unsafe_execute, in favor of explicit read/write security control using the `enabled_security` context manager. Also code executed on the repository side is now unsafe by default.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4834
diff changeset
    93
                        hook()
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    94
5093
8d073d2e089d [optimization] improve massive write performance by optimizing hooks selection
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5072
diff changeset
    95
class HooksManager(object):
8d073d2e089d [optimization] improve massive write performance by optimizing hooks selection
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5072
diff changeset
    96
    def __init__(self, vreg):
8d073d2e089d [optimization] improve massive write performance by optimizing hooks selection
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5072
diff changeset
    97
        self.vreg = vreg
8d073d2e089d [optimization] improve massive write performance by optimizing hooks selection
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5072
diff changeset
    98
8d073d2e089d [optimization] improve massive write performance by optimizing hooks selection
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5072
diff changeset
    99
    def call_hooks(self, event, session=None, **kwargs):
8d073d2e089d [optimization] improve massive write performance by optimizing hooks selection
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5072
diff changeset
   100
        try:
8d073d2e089d [optimization] improve massive write performance by optimizing hooks selection
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5072
diff changeset
   101
            self.vreg['%s_hooks' % event].call_hooks(event, session, **kwargs)
8d073d2e089d [optimization] improve massive write performance by optimizing hooks selection
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5072
diff changeset
   102
        except RegistryNotFound:
8d073d2e089d [optimization] improve massive write performance by optimizing hooks selection
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5072
diff changeset
   103
            pass # no hooks for this event
8d073d2e089d [optimization] improve massive write performance by optimizing hooks selection
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5072
diff changeset
   104
8d073d2e089d [optimization] improve massive write performance by optimizing hooks selection
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5072
diff changeset
   105
8d073d2e089d [optimization] improve massive write performance by optimizing hooks selection
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5072
diff changeset
   106
for event in ALL_HOOKS:
8d073d2e089d [optimization] improve massive write performance by optimizing hooks selection
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5072
diff changeset
   107
    VRegistry.REGISTRY_FACTORY['%s_hooks' % event] = HooksRegistry
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   108
4838
d4187a08ccdf [hook] entity_oldnew_value may cause bug on attributes explicitly set to None
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4699
diff changeset
   109
_MARKER = object()
4011
394f853bb653 [migration] write migration instructions for permissions handling on relation definition
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4008
diff changeset
   110
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
   111
    """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
   112
    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
   113
    """
394f853bb653 [migration] write migration instructions for permissions handling on relation definition
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4008
diff changeset
   114
    # 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
   115
    # fetch old value
4838
d4187a08ccdf [hook] entity_oldnew_value may cause bug on attributes explicitly set to None
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4699
diff changeset
   116
    newvalue = entity.pop(attr, _MARKER)
4011
394f853bb653 [migration] write migration instructions for permissions handling on relation definition
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4008
diff changeset
   117
    oldvalue = getattr(entity, attr)
4838
d4187a08ccdf [hook] entity_oldnew_value may cause bug on attributes explicitly set to None
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4699
diff changeset
   118
    if newvalue is not _MARKER:
4011
394f853bb653 [migration] write migration instructions for permissions handling on relation definition
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4008
diff changeset
   119
        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
   120
    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
   121
394f853bb653 [migration] write migration instructions for permissions handling on relation definition
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4008
diff changeset
   122
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   123
# some hook specific selectors #################################################
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   124
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   125
@objectify_selector
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   126
@lltrace
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   127
def enabled_category(cls, req, **kwargs):
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   128
    if req is None:
4834
b718626a0e60 move hooks activation control on session object, so we can have a per transaction control. Added a new `hooks_control` context manager for usual modification of hooks activation.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4699
diff changeset
   129
        return True # XXX how to deactivate server startup / shutdown event
b718626a0e60 move hooks activation control on session object, so we can have a per transaction control. Added a new `hooks_control` context manager for usual modification of hooks activation.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4699
diff changeset
   130
    return req.is_hook_activated(cls)
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   131
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   132
@objectify_selector
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   133
@lltrace
4835
13b0b96d7982 [repo] enhanced security handling: deprecates unsafe_execute, in favor of explicit read/write security control using the `enabled_security` context manager. Also code executed on the repository side is now unsafe by default.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4834
diff changeset
   134
def from_dbapi_query(cls, req, **kwargs):
13b0b96d7982 [repo] enhanced security handling: deprecates unsafe_execute, in favor of explicit read/write security control using the `enabled_security` context manager. Also code executed on the repository side is now unsafe by default.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4834
diff changeset
   135
    if req.running_dbapi_query:
13b0b96d7982 [repo] enhanced security handling: deprecates unsafe_execute, in favor of explicit read/write security control using the `enabled_security` context manager. Also code executed on the repository side is now unsafe by default.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4834
diff changeset
   136
        return 1
13b0b96d7982 [repo] enhanced security handling: deprecates unsafe_execute, in favor of explicit read/write security control using the `enabled_security` context manager. Also code executed on the repository side is now unsafe by default.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4834
diff changeset
   137
    return 0
3660
7b41a6ba7400 fix/prepare propagation hooks usage
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3659
diff changeset
   138
7b41a6ba7400 fix/prepare propagation hooks usage
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3659
diff changeset
   139
class rechain(object):
7b41a6ba7400 fix/prepare propagation hooks usage
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3659
diff changeset
   140
    def __init__(self, *iterators):
7b41a6ba7400 fix/prepare propagation hooks usage
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3659
diff changeset
   141
        self.iterators = iterators
7b41a6ba7400 fix/prepare propagation hooks usage
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3659
diff changeset
   142
    def __iter__(self):
7b41a6ba7400 fix/prepare propagation hooks usage
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3659
diff changeset
   143
        return iter(chain(*self.iterators))
7b41a6ba7400 fix/prepare propagation hooks usage
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3659
diff changeset
   144
7b41a6ba7400 fix/prepare propagation hooks usage
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3659
diff changeset
   145
4699
8757fca2c308 [hooks] match_rtype and match_rtype_sets don't need to extend match_search_state
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4522
diff changeset
   146
class match_rtype(ExpectedValueSelector):
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   147
    """accept if parameters specified as initializer arguments are specified
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   148
    in named arguments given to the selector
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   149
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   150
    :param *expected: parameters (eg `basestring`) which are expected to be
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   151
                      found in named arguments (kwargs)
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   152
    """
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
   153
    def __init__(self, *expected, **more):
3660
7b41a6ba7400 fix/prepare propagation hooks usage
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3659
diff changeset
   154
        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
   155
        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
   156
        self.toetypes = more.pop('toetypes', None)
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   157
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   158
    @lltrace
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   159
    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
   160
        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
   161
            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
   162
        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
   163
               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
   164
            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
   165
        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
   166
               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
   167
            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
   168
        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
   169
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   170
4699
8757fca2c308 [hooks] match_rtype and match_rtype_sets don't need to extend match_search_state
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4522
diff changeset
   171
class match_rtype_sets(ExpectedValueSelector):
4086
9b96126e0b14 add hook selector
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4075
diff changeset
   172
    """accept if parameters specified as initializer arguments are specified
9b96126e0b14 add hook selector
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4075
diff changeset
   173
    in named arguments given to the selector
9b96126e0b14 add hook selector
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4075
diff changeset
   174
    """
9b96126e0b14 add hook selector
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4075
diff changeset
   175
9b96126e0b14 add hook selector
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4075
diff changeset
   176
    def __init__(self, *expected):
9b96126e0b14 add hook selector
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4075
diff changeset
   177
        self.expected = expected
9b96126e0b14 add hook selector
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4075
diff changeset
   178
9b96126e0b14 add hook selector
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4075
diff changeset
   179
    @lltrace
9b96126e0b14 add hook selector
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4075
diff changeset
   180
    def __call__(self, cls, req, *args, **kwargs):
9b96126e0b14 add hook selector
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4075
diff changeset
   181
        for rel_set in self.expected:
9b96126e0b14 add hook selector
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4075
diff changeset
   182
            if kwargs.get('rtype') in rel_set:
9b96126e0b14 add hook selector
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4075
diff changeset
   183
                return 1
9b96126e0b14 add hook selector
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4075
diff changeset
   184
        return 0
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   185
5093
8d073d2e089d [optimization] improve massive write performance by optimizing hooks selection
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5072
diff changeset
   186
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   187
# base class for hook ##########################################################
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
class Hook(AppObject):
5093
8d073d2e089d [optimization] improve massive write performance by optimizing hooks selection
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5072
diff changeset
   190
    __select__ = enabled_category()
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   191
    # set this in derivated classes
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   192
    events = None
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   193
    category = None
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   194
    order = 0
2855
1d9be3dffa94 [repo] more deprecation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2847
diff changeset
   195
    # XXX deprecated
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   196
    enabled = True
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   197
5287
6346f1fd0a50 [hook] backport bad .events fix from default
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5220
diff changeset
   198
    @classmethod
6346f1fd0a50 [hook] backport bad .events fix from default
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5220
diff changeset
   199
    def check_events(cls):
5116
a2ce436e00ad [hooks] better message on bad .event class attribute
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5093
diff changeset
   200
        try:
5287
6346f1fd0a50 [hook] backport bad .events fix from default
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5220
diff changeset
   201
            for event in cls.events:
6346f1fd0a50 [hook] backport bad .events fix from default
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5220
diff changeset
   202
                if event not in ALL_HOOKS:
6346f1fd0a50 [hook] backport bad .events fix from default
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5220
diff changeset
   203
                    raise Exception('bad event %s on %s.%s' % (
6346f1fd0a50 [hook] backport bad .events fix from default
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5220
diff changeset
   204
                        event, cls.__module__, cls.__name__))
5116
a2ce436e00ad [hooks] better message on bad .event class attribute
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5093
diff changeset
   205
        except AttributeError:
a2ce436e00ad [hooks] better message on bad .event class attribute
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5093
diff changeset
   206
            raise
a2ce436e00ad [hooks] better message on bad .event class attribute
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5093
diff changeset
   207
        except TypeError:
a2ce436e00ad [hooks] better message on bad .event class attribute
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5093
diff changeset
   208
            raise Exception('bad .events attribute %s on %s.%s' % (
a2ce436e00ad [hooks] better message on bad .event class attribute
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5093
diff changeset
   209
                cls.events, cls.__module__, cls.__name__))
5093
8d073d2e089d [optimization] improve massive write performance by optimizing hooks selection
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5072
diff changeset
   210
8d073d2e089d [optimization] improve massive write performance by optimizing hooks selection
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5072
diff changeset
   211
    @classproperty
5287
6346f1fd0a50 [hook] backport bad .events fix from default
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5220
diff changeset
   212
    def __registries__(cls):
6346f1fd0a50 [hook] backport bad .events fix from default
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5220
diff changeset
   213
        cls.check_events()
6346f1fd0a50 [hook] backport bad .events fix from default
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5220
diff changeset
   214
        return ['%s_hooks' % ev for ev in cls.events]
6346f1fd0a50 [hook] backport bad .events fix from default
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5220
diff changeset
   215
6346f1fd0a50 [hook] backport bad .events fix from default
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5220
diff changeset
   216
    @classproperty
3376
f5c69485381f [appobjects] use __regid__ instead of __id__, more explicit
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3195
diff changeset
   217
    def __regid__(cls):
3383
c6aff16e5aed nicer warnings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   218
        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
   219
             % (cls.__module__, cls.__name__), DeprecationWarning)
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   220
        return str(id(cls))
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   221
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   222
    @classmethod
4490
d45cde54d464 backport stable branch and some vreg cleanups:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4341
diff changeset
   223
    def __registered__(cls, reg):
d45cde54d464 backport stable branch and some vreg cleanups:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4341
diff changeset
   224
        super(Hook, cls).__registered__(reg)
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   225
        if getattr(cls, 'accepts', None):
3383
c6aff16e5aed nicer warnings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   226
            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
   227
                 % (cls.__module__, cls.__name__), DeprecationWarning)
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   228
            rtypes = []
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   229
            for ertype in cls.accepts:
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   230
                if ertype.islower():
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   231
                    rtypes.append(ertype)
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   232
                else:
4075
e710f4052bd6 use implements instead of entity_implements
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4025
diff changeset
   233
                    cls.__select__ = cls.__select__ & implements(ertype)
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   234
            if rtypes:
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   235
                cls.__select__ = cls.__select__ & match_rtype(*rtypes)
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   236
        return cls
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   237
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   238
    known_args = set(('entity', 'rtype', 'eidfrom', 'eidto', 'repo', 'timestamp'))
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   239
    def __init__(self, req, event, **kwargs):
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   240
        for arg in self.known_args:
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   241
            if arg in kwargs:
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   242
                setattr(self, arg, kwargs.pop(arg))
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   243
        super(Hook, self).__init__(req, **kwargs)
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   244
        self.event = event
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   245
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   246
    def __call__(self):
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   247
        if hasattr(self, 'call'):
3383
c6aff16e5aed nicer warnings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   248
            cls = self.__class__
c6aff16e5aed nicer warnings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   249
            warn('[3.6] %s.%s: call is deprecated, implements __call__'
c6aff16e5aed nicer warnings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   250
                 % (cls.__module__, cls.__name__), DeprecationWarning)
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   251
            if self.event.endswith('_relation'):
2847
c2ee28f4d4b1 use ._cw instead of .cw_req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2840
diff changeset
   252
                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
   253
            elif 'delete' in self.event:
2847
c2ee28f4d4b1 use ._cw instead of .cw_req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2840
diff changeset
   254
                self.call(self._cw, self.entity.eid)
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   255
            elif self.event.startswith('server_'):
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   256
                self.call(self.repo)
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   257
            elif self.event.startswith('session_'):
2847
c2ee28f4d4b1 use ._cw instead of .cw_req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2840
diff changeset
   258
                self.call(self._cw)
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   259
            else:
2847
c2ee28f4d4b1 use ._cw instead of .cw_req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2840
diff changeset
   260
                self.call(self._cw, self.entity)
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   261
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   262
set_log_methods(Hook, getLogger('cubicweb.hook'))
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   263
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   264
2968
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   265
# 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
   266
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   267
class PropagateSubjectRelationHook(Hook):
4522
271f201e3735 propagation hooks cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4490
diff changeset
   268
    """propagate some `main_rtype` relation on entities linked as object of
271f201e3735 propagation hooks cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4490
diff changeset
   269
    `subject_relations` or as subject of `object_relations` (the watched
271f201e3735 propagation hooks cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4490
diff changeset
   270
    relations).
271f201e3735 propagation hooks cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4490
diff changeset
   271
271f201e3735 propagation hooks cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4490
diff changeset
   272
    This hook ensure that when one of the watched relation is added, the
271f201e3735 propagation hooks cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4490
diff changeset
   273
    `main_rtype` relation is added to the target entity of the relation.
271f201e3735 propagation hooks cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4490
diff changeset
   274
    """
2968
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   275
    events = ('after_add_relation',)
3660
7b41a6ba7400 fix/prepare propagation hooks usage
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3659
diff changeset
   276
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
    # to set in concrete class
3660
7b41a6ba7400 fix/prepare propagation hooks usage
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3659
diff changeset
   278
    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
   279
    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
   280
    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
   281
3659
993997b4b41d 3.6 update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3423
diff changeset
   282
    def __call__(self):
4522
271f201e3735 propagation hooks cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4490
diff changeset
   283
        assert self.main_rtype
3659
993997b4b41d 3.6 update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3423
diff changeset
   284
        for eid in (self.eidfrom, self.eidto):
993997b4b41d 3.6 update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3423
diff changeset
   285
            etype = self._cw.describe(eid)[0]
4522
271f201e3735 propagation hooks cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4490
diff changeset
   286
            if self.main_rtype not in self._cw.vreg.schema.eschema(etype).subjrels:
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
                return
3659
993997b4b41d 3.6 update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3423
diff changeset
   288
        if self.rtype in self.subject_relations:
993997b4b41d 3.6 update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3423
diff changeset
   289
            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
   290
        else:
3659
993997b4b41d 3.6 update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3423
diff changeset
   291
            assert self.rtype in self.object_relations
993997b4b41d 3.6 update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3423
diff changeset
   292
            meid, seid = self.eidto, self.eidfrom
4835
13b0b96d7982 [repo] enhanced security handling: deprecates unsafe_execute, in favor of explicit read/write security control using the `enabled_security` context manager. Also code executed on the repository side is now unsafe by default.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4834
diff changeset
   293
        self._cw.execute(
3090
8184bec7414d backport 3.5
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3087
diff changeset
   294
            '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
   295
            % (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
   296
            {'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
   297
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   298
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   299
class PropagateSubjectRelationAddHook(Hook):
4522
271f201e3735 propagation hooks cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4490
diff changeset
   300
    """propagate to entities at the end of watched relations when a `main_rtype`
271f201e3735 propagation hooks cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4490
diff changeset
   301
    relation is added
271f201e3735 propagation hooks cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4490
diff changeset
   302
    """
2968
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   303
    events = ('after_add_relation',)
3660
7b41a6ba7400 fix/prepare propagation hooks usage
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3659
diff changeset
   304
2968
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   305
    # to set in concrete class
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   306
    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
   307
    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
   308
3659
993997b4b41d 3.6 update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3423
diff changeset
   309
    def __call__(self):
4104
7e478d7caf20 [mq]: small_api_changes_for_3.6
Arthur Lutz <arthur.lutz@logilab.fr>
parents: 4086
diff changeset
   310
        eschema = self._cw.vreg.schema.eschema(self._cw.describe(self.eidfrom)[0])
4835
13b0b96d7982 [repo] enhanced security handling: deprecates unsafe_execute, in favor of explicit read/write security control using the `enabled_security` context manager. Also code executed on the repository side is now unsafe by default.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4834
diff changeset
   311
        execute = self._cw.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
   312
        for rel in self.subject_relations:
3720
5376aaadd16b backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3660
diff changeset
   313
            if rel in eschema.subjrels:
3090
8184bec7414d backport 3.5
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3087
diff changeset
   314
                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
   315
                        '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
   316
                        {'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
   317
        for rel in self.object_relations:
3720
5376aaadd16b backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3660
diff changeset
   318
            if rel in eschema.objrels:
3090
8184bec7414d backport 3.5
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3087
diff changeset
   319
                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
   320
                        '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
   321
                        {'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
   322
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   323
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   324
class PropagateSubjectRelationDelHook(Hook):
4522
271f201e3735 propagation hooks cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4490
diff changeset
   325
    """propagate to entities at the end of watched relations when a `main_rtype`
271f201e3735 propagation hooks cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4490
diff changeset
   326
    relation is deleted
271f201e3735 propagation hooks cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4490
diff changeset
   327
    """
2968
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   328
    events = ('after_delete_relation',)
3660
7b41a6ba7400 fix/prepare propagation hooks usage
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3659
diff changeset
   329
2968
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   330
    # to set in concrete class
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   331
    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
   332
    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
   333
3659
993997b4b41d 3.6 update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3423
diff changeset
   334
    def __call__(self):
4104
7e478d7caf20 [mq]: small_api_changes_for_3.6
Arthur Lutz <arthur.lutz@logilab.fr>
parents: 4086
diff changeset
   335
        eschema = self._cw.vreg.schema.eschema(self._cw.describe(self.eidfrom)[0])
4835
13b0b96d7982 [repo] enhanced security handling: deprecates unsafe_execute, in favor of explicit read/write security control using the `enabled_security` context manager. Also code executed on the repository side is now unsafe by default.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4834
diff changeset
   336
        execute = self._cw.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
   337
        for rel in self.subject_relations:
3720
5376aaadd16b backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3660
diff changeset
   338
            if rel in eschema.subjrels:
3090
8184bec7414d backport 3.5
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3087
diff changeset
   339
                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
   340
                        'X %s R' % (self.rtype, rel),
993997b4b41d 3.6 update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3423
diff changeset
   341
                        {'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
   342
        for rel in self.object_relations:
3720
5376aaadd16b backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3660
diff changeset
   343
            if rel in eschema.objrels:
3090
8184bec7414d backport 3.5
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3087
diff changeset
   344
                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
   345
                        'R %s X' % (self.rtype, rel),
993997b4b41d 3.6 update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3423
diff changeset
   346
                        {'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
   347
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   348
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   349
# abstract classes for operation ###############################################
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   350
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   351
class Operation(object):
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   352
    """an operation is triggered on connections pool events related to
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   353
    commit / rollback transations. Possible events are:
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   354
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   355
    precommit:
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   356
      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
   357
      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
   358
      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
   359
      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
   360
      event won't be triggered
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   361
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   362
    commit:
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   363
      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
   364
      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
   365
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   366
    revertcommit:
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   367
      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
   368
      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
   369
      revert things (including the operation which made fail the commit)
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
    rollback:
5220
42f854b6083d [doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 5194
diff changeset
   372
      the transaction has been either rollbacked either:
42f854b6083d [doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 5194
diff changeset
   373
       * intentionaly
42f854b6083d [doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 5194
diff changeset
   374
       * a precommit event failed, all operations are rollbacked
42f854b6083d [doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 5194
diff changeset
   375
       * a commit event failed, all operations which are not been triggered for
42f854b6083d [doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 5194
diff changeset
   376
         commit are rollbacked
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   377
5220
42f854b6083d [doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 5194
diff changeset
   378
    order of operations may be important, and is controlled according to
42f854b6083d [doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 5194
diff changeset
   379
    the insert_index's method output
2835
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
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   382
    def __init__(self, session, **kwargs):
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   383
        self.session = session
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   384
        self.__dict__.update(kwargs)
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   385
        self.register(session)
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   386
        # execution information
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   387
        self.processed = None # 'precommit', 'commit'
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   388
        self.failed = False
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   389
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   390
    def register(self, session):
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   391
        session.add_operation(self, self.insert_index())
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   392
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   393
    def insert_index(self):
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   394
        """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
   395
        LateOperation instance
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   396
        """
3720
5376aaadd16b backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3660
diff changeset
   397
        # faster by inspecting operation in reverse order for heavy transactions
5376aaadd16b backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3660
diff changeset
   398
        i = None
5376aaadd16b backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3660
diff changeset
   399
        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
   400
            if isinstance(op, (LateOperation, SingleLastOperation)):
3720
5376aaadd16b backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3660
diff changeset
   401
                continue
5376aaadd16b backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3660
diff changeset
   402
            return -i or None
5376aaadd16b backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3660
diff changeset
   403
        if i is None:
5376aaadd16b backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3660
diff changeset
   404
            return None
5376aaadd16b backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3660
diff changeset
   405
        return -(i + 1)
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   406
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   407
    def handle_event(self, event):
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   408
        """delegate event handling to the opertaion"""
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   409
        getattr(self, event)()
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   410
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   411
    def precommit_event(self):
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   412
        """the observed connections pool is preparing a commit"""
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   413
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   414
    def revertprecommit_event(self):
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   415
        """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
   416
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   417
        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
   418
        been all considered if it's this operation which failed
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   419
        """
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   420
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   421
    def commit_event(self):
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   422
        """the observed connections pool is commiting"""
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   423
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   424
    def revertcommit_event(self):
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   425
        """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
   426
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   427
        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
   428
        been all considered if it's this operation which failed
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   429
        """
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   430
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   431
    def rollback_event(self):
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   432
        """the observed connections pool has been rollbacked
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   433
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   434
        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
   435
        operation list
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   436
        """
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   437
3998
94cc7cad3d2d backport stable into default
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3720
diff changeset
   438
    def postcommit_event(self):
94cc7cad3d2d backport stable into default
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3720
diff changeset
   439
        """the observed connections pool has committed"""
94cc7cad3d2d backport stable into default
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3720
diff changeset
   440
2855
1d9be3dffa94 [repo] more deprecation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2847
diff changeset
   441
    @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
   442
    @deprecated('[3.6] use self.session.user')
2855
1d9be3dffa94 [repo] more deprecation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2847
diff changeset
   443
    def user(self):
1d9be3dffa94 [repo] more deprecation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2847
diff changeset
   444
        return self.session.user
1d9be3dffa94 [repo] more deprecation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2847
diff changeset
   445
1d9be3dffa94 [repo] more deprecation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2847
diff changeset
   446
    @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
   447
    @deprecated('[3.6] use self.session.repo')
2855
1d9be3dffa94 [repo] more deprecation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2847
diff changeset
   448
    def repo(self):
1d9be3dffa94 [repo] more deprecation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2847
diff changeset
   449
        return self.session.repo
1d9be3dffa94 [repo] more deprecation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2847
diff changeset
   450
1d9be3dffa94 [repo] more deprecation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2847
diff changeset
   451
    @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
   452
    @deprecated('[3.6] use self.session.vreg.schema')
2855
1d9be3dffa94 [repo] more deprecation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2847
diff changeset
   453
    def schema(self):
1d9be3dffa94 [repo] more deprecation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2847
diff changeset
   454
        return self.session.repo.schema
1d9be3dffa94 [repo] more deprecation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2847
diff changeset
   455
1d9be3dffa94 [repo] more deprecation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2847
diff changeset
   456
    @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
   457
    @deprecated('[3.6] use self.session.vreg.config')
2855
1d9be3dffa94 [repo] more deprecation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2847
diff changeset
   458
    def config(self):
1d9be3dffa94 [repo] more deprecation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2847
diff changeset
   459
        return self.session.repo.config
1d9be3dffa94 [repo] more deprecation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2847
diff changeset
   460
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   461
set_log_methods(Operation, getLogger('cubicweb.session'))
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   462
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   463
5060
ee3b856e1406 [repo] optimize massive insertion/deletion by using the new set_operation function
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5019
diff changeset
   464
def set_operation(session, datakey, value, opcls, **opkwargs):
ee3b856e1406 [repo] optimize massive insertion/deletion by using the new set_operation function
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5019
diff changeset
   465
    """Search for session.transaction_data[`datakey`] (expected to be a set):
ee3b856e1406 [repo] optimize massive insertion/deletion by using the new set_operation function
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5019
diff changeset
   466
ee3b856e1406 [repo] optimize massive insertion/deletion by using the new set_operation function
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5019
diff changeset
   467
    * if found, simply append `value`
ee3b856e1406 [repo] optimize massive insertion/deletion by using the new set_operation function
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5019
diff changeset
   468
ee3b856e1406 [repo] optimize massive insertion/deletion by using the new set_operation function
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5019
diff changeset
   469
    * else, initialize it to set([`value`]) and instantiate the given `opcls`
ee3b856e1406 [repo] optimize massive insertion/deletion by using the new set_operation function
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5019
diff changeset
   470
      operation class with additional keyword arguments.
ee3b856e1406 [repo] optimize massive insertion/deletion by using the new set_operation function
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5019
diff changeset
   471
ee3b856e1406 [repo] optimize massive insertion/deletion by using the new set_operation function
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5019
diff changeset
   472
    You should use this instead of creating on operation for each `value`,
ee3b856e1406 [repo] optimize massive insertion/deletion by using the new set_operation function
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5019
diff changeset
   473
    since handling operations becomes coslty on massive data import.
ee3b856e1406 [repo] optimize massive insertion/deletion by using the new set_operation function
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5019
diff changeset
   474
    """
ee3b856e1406 [repo] optimize massive insertion/deletion by using the new set_operation function
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5019
diff changeset
   475
    try:
ee3b856e1406 [repo] optimize massive insertion/deletion by using the new set_operation function
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5019
diff changeset
   476
        session.transaction_data[datakey].add(value)
ee3b856e1406 [repo] optimize massive insertion/deletion by using the new set_operation function
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5019
diff changeset
   477
    except KeyError:
5194
395f076512a1 [hooks] fix set_operation options passing (** -> *)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 5191
diff changeset
   478
        opcls(session, **opkwargs)
5060
ee3b856e1406 [repo] optimize massive insertion/deletion by using the new set_operation function
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5019
diff changeset
   479
        session.transaction_data[datakey] = set((value,))
ee3b856e1406 [repo] optimize massive insertion/deletion by using the new set_operation function
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5019
diff changeset
   480
ee3b856e1406 [repo] optimize massive insertion/deletion by using the new set_operation function
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5019
diff changeset
   481
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   482
class LateOperation(Operation):
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   483
    """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
   484
    operations
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   485
    """
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   486
    def insert_index(self):
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   487
        """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
   488
        SingleLastOperation instance
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   489
        """
3720
5376aaadd16b backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3660
diff changeset
   490
        # faster by inspecting operation in reverse order for heavy transactions
5376aaadd16b backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3660
diff changeset
   491
        i = None
5376aaadd16b backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3660
diff changeset
   492
        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
   493
            if isinstance(op, SingleLastOperation):
3720
5376aaadd16b backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3660
diff changeset
   494
                continue
5376aaadd16b backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3660
diff changeset
   495
            return -i or None
5376aaadd16b backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3660
diff changeset
   496
        if i is None:
5376aaadd16b backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3660
diff changeset
   497
            return None
5376aaadd16b backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3660
diff changeset
   498
        return -(i + 1)
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   499
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   500
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   501
class SingleOperation(Operation):
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   502
    """special operation which should be called once"""
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   503
    def register(self, session):
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   504
        """override register to handle cases where this operation has already
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   505
        been added
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   506
        """
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   507
        operations = session.pending_operations
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   508
        index = self.equivalent_index(operations)
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   509
        if index is not None:
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   510
            equivalent = operations.pop(index)
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   511
        else:
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   512
            equivalent = None
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   513
        session.add_operation(self, self.insert_index())
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   514
        return equivalent
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   515
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   516
    def equivalent_index(self, operations):
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   517
        """return the index of the equivalent operation if any"""
3720
5376aaadd16b backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3660
diff changeset
   518
        for i, op in enumerate(reversed(operations)):
5376aaadd16b backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3660
diff changeset
   519
            if op.__class__ is self.__class__:
5376aaadd16b backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3660
diff changeset
   520
                return -(i+1)
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   521
        return None
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   522
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   523
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   524
class SingleLastOperation(SingleOperation):
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   525
    """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
   526
    operations
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   527
    """
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   528
    def insert_index(self):
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   529
        return None
2840
06daf13195d4 [hooks] deprecates hookhelper module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2835
diff changeset
   530
06daf13195d4 [hooks] deprecates hookhelper module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2835
diff changeset
   531
06daf13195d4 [hooks] deprecates hookhelper module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2835
diff changeset
   532
class SendMailOp(SingleLastOperation):
06daf13195d4 [hooks] deprecates hookhelper module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2835
diff changeset
   533
    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
   534
        # may not specify msg yet, as
06daf13195d4 [hooks] deprecates hookhelper module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2835
diff changeset
   535
        # `cubicweb.sobjects.supervision.SupervisionMailOp`
06daf13195d4 [hooks] deprecates hookhelper module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2835
diff changeset
   536
        if msg is not None:
06daf13195d4 [hooks] deprecates hookhelper module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2835
diff changeset
   537
            assert recipients
06daf13195d4 [hooks] deprecates hookhelper module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2835
diff changeset
   538
            self.to_send = [(msg, recipients)]
06daf13195d4 [hooks] deprecates hookhelper module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2835
diff changeset
   539
        else:
06daf13195d4 [hooks] deprecates hookhelper module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2835
diff changeset
   540
            assert recipients is None
06daf13195d4 [hooks] deprecates hookhelper module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2835
diff changeset
   541
            self.to_send = []
06daf13195d4 [hooks] deprecates hookhelper module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2835
diff changeset
   542
        super(SendMailOp, self).__init__(session, **kwargs)
06daf13195d4 [hooks] deprecates hookhelper module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2835
diff changeset
   543
06daf13195d4 [hooks] deprecates hookhelper module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2835
diff changeset
   544
    def register(self, session):
06daf13195d4 [hooks] deprecates hookhelper module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2835
diff changeset
   545
        previous = super(SendMailOp, self).register(session)
06daf13195d4 [hooks] deprecates hookhelper module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2835
diff changeset
   546
        if previous:
06daf13195d4 [hooks] deprecates hookhelper module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2835
diff changeset
   547
            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
   548
06daf13195d4 [hooks] deprecates hookhelper module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2835
diff changeset
   549
    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
   550
        self.session.repo.threaded_task(self.sendmails)
2840
06daf13195d4 [hooks] deprecates hookhelper module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2835
diff changeset
   551
06daf13195d4 [hooks] deprecates hookhelper module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2835
diff changeset
   552
    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
   553
        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
   554
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   555
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2855
diff changeset
   556
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
   557
    def precommit_event(self):
4835
13b0b96d7982 [repo] enhanced security handling: deprecates unsafe_execute, in favor of explicit read/write security control using the `enabled_security` context manager. Also code executed on the repository side is now unsafe by default.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4834
diff changeset
   558
        execute = self.session.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
   559
        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
   560
            execute(*rql)
5067
adc2122eed03 [repo] more efficient eid cache operations handling based on set_operation; refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5060
diff changeset
   561
adc2122eed03 [repo] more efficient eid cache operations handling based on set_operation; refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5060
diff changeset
   562
adc2122eed03 [repo] more efficient eid cache operations handling based on set_operation; refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5060
diff changeset
   563
class CleanupNewEidsCacheOp(SingleLastOperation):
adc2122eed03 [repo] more efficient eid cache operations handling based on set_operation; refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5060
diff changeset
   564
    """on rollback of a insert query we have to remove from repository's
adc2122eed03 [repo] more efficient eid cache operations handling based on set_operation; refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5060
diff changeset
   565
    type/source cache eids of entities added in that transaction.
adc2122eed03 [repo] more efficient eid cache operations handling based on set_operation; refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5060
diff changeset
   566
adc2122eed03 [repo] more efficient eid cache operations handling based on set_operation; refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5060
diff changeset
   567
    NOTE: querier's rqlst/solutions cache may have been polluted too with
adc2122eed03 [repo] more efficient eid cache operations handling based on set_operation; refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5060
diff changeset
   568
    queries such as Any X WHERE X eid 32 if 32 has been rollbacked however
adc2122eed03 [repo] more efficient eid cache operations handling based on set_operation; refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5060
diff changeset
   569
    generated queries are unpredictable and analysing all the cache probably
adc2122eed03 [repo] more efficient eid cache operations handling based on set_operation; refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5060
diff changeset
   570
    too expensive. Notice that there is no pb when using args to specify eids
adc2122eed03 [repo] more efficient eid cache operations handling based on set_operation; refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5060
diff changeset
   571
    instead of giving them into the rql string.
adc2122eed03 [repo] more efficient eid cache operations handling based on set_operation; refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5060
diff changeset
   572
    """
adc2122eed03 [repo] more efficient eid cache operations handling based on set_operation; refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5060
diff changeset
   573
adc2122eed03 [repo] more efficient eid cache operations handling based on set_operation; refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5060
diff changeset
   574
    def rollback_event(self):
adc2122eed03 [repo] more efficient eid cache operations handling based on set_operation; refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5060
diff changeset
   575
        """the observed connections pool has been rollbacked,
adc2122eed03 [repo] more efficient eid cache operations handling based on set_operation; refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5060
diff changeset
   576
        remove inserted eid from repository type/source cache
adc2122eed03 [repo] more efficient eid cache operations handling based on set_operation; refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5060
diff changeset
   577
        """
adc2122eed03 [repo] more efficient eid cache operations handling based on set_operation; refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5060
diff changeset
   578
        try:
adc2122eed03 [repo] more efficient eid cache operations handling based on set_operation; refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5060
diff changeset
   579
            self.session.repo.clear_caches(
adc2122eed03 [repo] more efficient eid cache operations handling based on set_operation; refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5060
diff changeset
   580
                self.session.transaction_data['neweids'])
adc2122eed03 [repo] more efficient eid cache operations handling based on set_operation; refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5060
diff changeset
   581
        except KeyError:
adc2122eed03 [repo] more efficient eid cache operations handling based on set_operation; refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5060
diff changeset
   582
            pass
adc2122eed03 [repo] more efficient eid cache operations handling based on set_operation; refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5060
diff changeset
   583
adc2122eed03 [repo] more efficient eid cache operations handling based on set_operation; refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5060
diff changeset
   584
class CleanupDeletedEidsCacheOp(SingleLastOperation):
adc2122eed03 [repo] more efficient eid cache operations handling based on set_operation; refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5060
diff changeset
   585
    """on commit of delete query, we have to remove from repository's
adc2122eed03 [repo] more efficient eid cache operations handling based on set_operation; refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5060
diff changeset
   586
    type/source cache eids of entities deleted in that transaction.
adc2122eed03 [repo] more efficient eid cache operations handling based on set_operation; refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5060
diff changeset
   587
    """
adc2122eed03 [repo] more efficient eid cache operations handling based on set_operation; refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5060
diff changeset
   588
adc2122eed03 [repo] more efficient eid cache operations handling based on set_operation; refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5060
diff changeset
   589
    def commit_event(self):
adc2122eed03 [repo] more efficient eid cache operations handling based on set_operation; refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5060
diff changeset
   590
        """the observed connections pool has been rollbacked,
adc2122eed03 [repo] more efficient eid cache operations handling based on set_operation; refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5060
diff changeset
   591
        remove inserted eid from repository type/source cache
adc2122eed03 [repo] more efficient eid cache operations handling based on set_operation; refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5060
diff changeset
   592
        """
adc2122eed03 [repo] more efficient eid cache operations handling based on set_operation; refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5060
diff changeset
   593
        try:
adc2122eed03 [repo] more efficient eid cache operations handling based on set_operation; refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5060
diff changeset
   594
            self.session.repo.clear_caches(
adc2122eed03 [repo] more efficient eid cache operations handling based on set_operation; refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5060
diff changeset
   595
                self.session.transaction_data['pendingeids'])
adc2122eed03 [repo] more efficient eid cache operations handling based on set_operation; refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5060
diff changeset
   596
        except KeyError:
adc2122eed03 [repo] more efficient eid cache operations handling based on set_operation; refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5060
diff changeset
   597
            pass