hooks/synccomputed.py
author Julien Cristau <julien.cristau@logilab.fr>
Thu, 12 Feb 2015 13:52:58 +0100
changeset 10231 fdcc500002ef
parent 10192 365e5a0287d6
child 10395 7e311ee8b5b0
permissions -rw-r--r--
[devtools] don't hide warnings and errors during tests The markdown module in jessie turns all warnings into logging calls, so this allows me to still see deprecation warnings when running tests.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
9967
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
     1
# copyright 2014 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
     2
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
     3
#
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
     4
# This file is part of CubicWeb.
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
     5
#
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
     6
# CubicWeb is free software: you can redistribute it and/or modify it under the
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
     7
# terms of the GNU Lesser General Public License as published by the Free
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
     8
# Software Foundation, either version 2.1 of the License, or (at your option)
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
     9
# any later version.
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    10
#
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    11
# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    12
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    13
# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    14
# details.
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    15
#
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    16
# You should have received a copy of the GNU Lesser General Public License along
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    17
# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    18
"""Hooks for synchronizing computed attributes"""
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    19
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    20
__docformat__ = "restructuredtext en"
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    21
_ = unicode
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    22
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    23
from collections import defaultdict
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    24
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    25
from rql import nodes
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    26
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    27
from cubicweb.server import hook
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    28
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    29
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    30
class RecomputeAttributeOperation(hook.DataOperationMixIn, hook.Operation):
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    31
    """Operation to recompute caches of computed attribute at commit time,
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    32
    depending on what's have been modified in the transaction and avoiding to
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    33
    recompute twice the same attribute
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    34
    """
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    35
    containercls = dict
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    36
    def add_data(self, computed_attribute, eid=None):
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    37
        try:
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    38
            self._container[computed_attribute].add(eid)
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    39
        except KeyError:
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    40
            self._container[computed_attribute] = set((eid,))
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    41
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    42
    def precommit_event(self):
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    43
        for computed_attribute_rdef, eids in self.get_data().iteritems():
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    44
            attr = computed_attribute_rdef.rtype
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    45
            formula  = computed_attribute_rdef.formula
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    46
            rql = formula.replace('Any ', 'Any X, ', 1)
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    47
            kwargs = None
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    48
            # add constraint on X to the formula
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    49
            if None in eids : # recompute for all etype if None is found
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    50
                rql += ', X is %s' % computed_attribute_rdef.subject
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    51
            elif len(eids) == 1:
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    52
                rql += ', X eid %(x)s'
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    53
                kwargs = {'x': eids.pop()}
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    54
            else:
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    55
                rql += ', X eid IN (%s)' % ', '.join((str(eid) for eid in eids))
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    56
            update_rql = 'SET X %s %%(value)s WHERE X eid %%(x)s' % attr
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    57
            for eid, value in self.cnx.execute(rql, kwargs):
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    58
                self.cnx.execute(update_rql, {'value': value, 'x': eid})
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    59
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    60
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    61
class EntityWithCACreatedHook(hook.Hook):
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    62
    """When creating an entity that has some computed attribute, those
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    63
    attributes have to be computed.
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    64
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    65
    Concret class of this hook are generated at registration time by
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    66
    introspecting the schema.
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    67
    """
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    68
    __abstract__ = True
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    69
    events = ('after_add_entity',)
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    70
    # list of computed attribute rdefs that have to be recomputed
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    71
    computed_attributes = None
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    72
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    73
    def __call__(self):
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    74
        for rdef in self.computed_attributes:
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    75
            RecomputeAttributeOperation.get_instance(self._cw).add_data(
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    76
                rdef, self.entity.eid)
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    77
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    78
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    79
class RelationInvolvedInCAModifiedHook(hook.Hook):
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    80
    """When some relation used in a computed attribute is updated, those
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    81
    attributes have to be recomputed.
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    82
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    83
    Concret class of this hook are generated at registration time by
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    84
    introspecting the schema.
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    85
    """
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    86
    __abstract__ = True
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    87
    events = ('after_add_relation', 'before_delete_relation')
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    88
    # list of (computed attribute rdef, optimize_on) that have to be recomputed
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    89
    optimized_computed_attributes = None
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    90
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    91
    def __call__(self):
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    92
        for rdef, optimize_on in self.optimized_computed_attributes:
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    93
            if optimize_on is None:
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    94
                eid = None
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    95
            else:
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    96
                eid = getattr(self, optimize_on)
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    97
            RecomputeAttributeOperation.get_instance(self._cw).add_data(rdef, eid)
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    98
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    99
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   100
class AttributeInvolvedInCAModifiedHook(hook.Hook):
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   101
    """When some attribute used in a computed attribute is updated, those
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   102
    attributes have to be recomputed.
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   103
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   104
    Concret class of this hook are generated at registration time by
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   105
    introspecting the schema.
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   106
    """
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   107
    __abstract__ = True
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   108
    events = ('after_update_entity',)
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   109
    # list of (computed attribute rdef, attributes of this entity type involved)
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   110
    # that may have to be recomputed
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   111
    attributes_computed_attributes = None
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   112
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   113
    def __call__(self):
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   114
        edited_attributes = frozenset(self.entity.cw_edited)
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   115
        for rdef, used_attributes in self.attributes_computed_attributes.iteritems():
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   116
            if edited_attributes.intersection(used_attributes):
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   117
                # XXX optimize if the modified attributes belong to the same
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   118
                # entity as the computed attribute
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   119
                RecomputeAttributeOperation.get_instance(self._cw).add_data(rdef)
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   120
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   121
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   122
# code generation at registration time #########################################
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   123
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   124
def _optimize_on(formula_select, rtype):
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   125
    """Given a formula and some rtype, tells whether on update of the given
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   126
    relation, formula may be recomputed only for rhe relation's subject
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   127
    ('eidfrom' returned), object ('eidto' returned) or None.
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   128
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   129
    Optimizing is only possible when X is used as direct subject/object of this
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   130
    relation, else we may miss some necessary update.
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   131
    """
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   132
    for rel in formula_select.get_nodes(nodes.Relation):
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   133
        if rel.r_type == rtype:
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   134
            sub = rel.get_variable_parts()[0]
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   135
            obj = rel.get_variable_parts()[1]
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   136
            if sub.name == 'X':
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   137
                return 'eidfrom'
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   138
            elif obj.name == 'X':
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   139
                return 'eidto'
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   140
            else:
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   141
                return None
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   142
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   143
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   144
class _FormulaDependenciesMatrix(object):
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   145
    """This class computes and represents the dependencies of computed attributes
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   146
    towards relations and attributes
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   147
    """
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   148
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   149
    def __init__(self, schema):
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   150
        """Analyzes the schema to compute the dependencies"""
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   151
        # entity types holding some computed attribute {etype: [computed rdefs]}
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   152
        self.computed_attribute_by_etype = defaultdict(list)
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   153
        # depending entity types {dep. etype: {computed rdef: dep. etype attributes}}
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   154
        self.computed_attribute_by_etype_attrs = defaultdict(lambda: defaultdict(set))
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   155
        # depending relations def {dep. rdef: [computed rdefs]
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   156
        self.computed_attribute_by_relation = defaultdict(list) # by rdef
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   157
        # Walk through all attributes definitions
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   158
        for rdef in schema.iter_computed_attributes():
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   159
            self.computed_attribute_by_etype[rdef.subject.type].append(rdef)
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   160
            # extract the relations it depends upon - `rdef.formula_select` is
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   161
            # expected to have been set by finalize_computed_attributes
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   162
            select = rdef.formula_select
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   163
            for rel_node in select.get_nodes(nodes.Relation):
10192
365e5a0287d6 [computed attribute] ensure attribute's formula apply only to the correct type. Closes #4901163
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9967
diff changeset
   164
                if rel_node.is_types_restriction():
365e5a0287d6 [computed attribute] ensure attribute's formula apply only to the correct type. Closes #4901163
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9967
diff changeset
   165
                    continue
9967
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   166
                rschema = schema.rschema(rel_node.r_type)
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   167
                lhs, rhs = rel_node.get_variable_parts()
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   168
                for sol in select.solutions:
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   169
                    subject_etype = sol[lhs.name]
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   170
                    if isinstance(rhs, nodes.VariableRef):
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   171
                        object_etypes = set(sol[rhs.name] for sol in select.solutions)
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   172
                    else:
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   173
                        object_etypes = rschema.objects(subject_etype)
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   174
                    for object_etype in object_etypes:
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   175
                        if rschema.final:
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   176
                            attr_for_computations = self.computed_attribute_by_etype_attrs[subject_etype]
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   177
                            attr_for_computations[rdef].add(rschema.type)
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   178
                        else:
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   179
                            depend_on_rdef = rschema.rdefs[subject_etype, object_etype]
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   180
                            self.computed_attribute_by_relation[depend_on_rdef].append(rdef)
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   181
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   182
    def generate_entity_creation_hooks(self):
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   183
        for etype, computed_attributes in self.computed_attribute_by_etype.iteritems():
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   184
            regid = 'computed_attribute.%s_created' % etype
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   185
            selector = hook.is_instance(etype)
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   186
            yield type('%sCreatedHook' % etype,
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   187
                       (EntityWithCACreatedHook,),
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   188
                       {'__regid__': regid,
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   189
                        '__select__':  hook.Hook.__select__ & selector,
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   190
                        'computed_attributes': computed_attributes})
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   191
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   192
    def generate_relation_change_hooks(self):
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   193
        for rdef, computed_attributes in self.computed_attribute_by_relation.iteritems():
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   194
            regid = 'computed_attribute.%s_modified' % rdef.rtype
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   195
            selector = hook.match_rtype(rdef.rtype.type,
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   196
                                        frometypes=(rdef.subject.type,),
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   197
                                        toetypes=(rdef.object.type,))
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   198
            optimized_computed_attributes = []
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   199
            for computed_rdef in computed_attributes:
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   200
                optimized_computed_attributes.append(
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   201
                    (computed_rdef,
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   202
                     _optimize_on(computed_rdef.formula_select, rdef.rtype))
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   203
                     )
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   204
            yield type('%sModifiedHook' % rdef.rtype,
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   205
                       (RelationInvolvedInCAModifiedHook,),
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   206
                       {'__regid__': regid,
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   207
                        '__select__':  hook.Hook.__select__ & selector,
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   208
                        'optimized_computed_attributes': optimized_computed_attributes})
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   209
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   210
    def generate_entity_update_hooks(self):
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   211
        for etype, attributes_computed_attributes in self.computed_attribute_by_etype_attrs.iteritems():
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   212
            regid = 'computed_attribute.%s_updated' % etype
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   213
            selector = hook.is_instance(etype)
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   214
            yield type('%sModifiedHook' % etype,
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   215
                       (AttributeInvolvedInCAModifiedHook,),
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   216
                       {'__regid__': regid,
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   217
                        '__select__':  hook.Hook.__select__ & selector,
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   218
                        'attributes_computed_attributes': attributes_computed_attributes})
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   219
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   220
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   221
def registration_callback(vreg):
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   222
    vreg.register_all(globals().values(), __name__)
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   223
    dependencies = _FormulaDependenciesMatrix(vreg.schema)
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   224
    for hook_class in dependencies.generate_entity_creation_hooks():
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   225
        vreg.register(hook_class)
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   226
    for hook_class in dependencies.generate_relation_change_hooks():
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   227
        vreg.register(hook_class)
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   228
    for hook_class in dependencies.generate_entity_update_hooks():
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   229
        vreg.register(hook_class)