author | Sylvain Thénault <sylvain.thenault@logilab.fr> |
Mon, 15 Feb 2010 17:47:50 +0100 | |
branch | stable |
changeset 4585 | 912aba7e6400 |
parent 4530 | a3c1549a68c6 |
child 4835 | 13b0b96d7982 |
permissions | -rw-r--r-- |
2835
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
1 |
"""Core hooks: check for data integrity according to the instance'schema |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
2 |
validity |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
3 |
|
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
4 |
:organization: Logilab |
4307
7fba9c34c88f
update copyright
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4190
diff
changeset
|
5 |
: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
|
6 |
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
7 |
: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
|
8 |
""" |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
9 |
__docformat__ = "restructuredtext en" |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
10 |
|
4490
d45cde54d464
backport stable branch and some vreg cleanups:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4307
diff
changeset
|
11 |
from threading import Lock |
d45cde54d464
backport stable branch and some vreg cleanups:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4307
diff
changeset
|
12 |
|
2835
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
13 |
from cubicweb import ValidationError |
3998
94cc7cad3d2d
backport stable into default
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3894
diff
changeset
|
14 |
from cubicweb.schema import RQLConstraint, RQLUniqueConstraint |
4075
e710f4052bd6
use implements instead of entity_implements
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4027
diff
changeset
|
15 |
from cubicweb.selectors import implements |
4023
eae23c40627a
drop common subpackage
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4003
diff
changeset
|
16 |
from cubicweb.uilib import soup2xhtml |
2841
107ba1c45227
rewrite hooks in sobjects as new Hook style into hooks sub-package
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2835
diff
changeset
|
17 |
from cubicweb.server import hook |
2835
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 |
# special relations that don't have to be checked for integrity, usually |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
20 |
# because they are handled internally by hooks (so we trust ourselves) |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
21 |
DONT_CHECK_RTYPES_ON_ADD = set(('owned_by', 'created_by', |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
22 |
'is', 'is_instance_of', |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
23 |
'wf_info_for', 'from_state', 'to_state')) |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
24 |
DONT_CHECK_RTYPES_ON_DEL = set(('is', 'is_instance_of', |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
25 |
'wf_info_for', 'from_state', 'to_state')) |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
26 |
|
4490
d45cde54d464
backport stable branch and some vreg cleanups:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4307
diff
changeset
|
27 |
_UNIQUE_CONSTRAINTS_LOCK = Lock() |
d45cde54d464
backport stable branch and some vreg cleanups:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4307
diff
changeset
|
28 |
_UNIQUE_CONSTRAINTS_HOLDER = None |
d45cde54d464
backport stable branch and some vreg cleanups:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4307
diff
changeset
|
29 |
|
4517
0f3c10fc42b2
backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4498
diff
changeset
|
30 |
|
4490
d45cde54d464
backport stable branch and some vreg cleanups:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4307
diff
changeset
|
31 |
def _acquire_unique_cstr_lock(session): |
d45cde54d464
backport stable branch and some vreg cleanups:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4307
diff
changeset
|
32 |
"""acquire the _UNIQUE_CONSTRAINTS_LOCK for the session. |
d45cde54d464
backport stable branch and some vreg cleanups:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4307
diff
changeset
|
33 |
|
d45cde54d464
backport stable branch and some vreg cleanups:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4307
diff
changeset
|
34 |
This lock used to avoid potential integrity pb when checking |
d45cde54d464
backport stable branch and some vreg cleanups:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4307
diff
changeset
|
35 |
RQLUniqueConstraint in two different transactions, as explained in |
d45cde54d464
backport stable branch and some vreg cleanups:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4307
diff
changeset
|
36 |
http://intranet.logilab.fr/jpl/ticket/36564 |
d45cde54d464
backport stable branch and some vreg cleanups:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4307
diff
changeset
|
37 |
""" |
d45cde54d464
backport stable branch and some vreg cleanups:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4307
diff
changeset
|
38 |
asession = session.actual_session() |
4517
0f3c10fc42b2
backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4498
diff
changeset
|
39 |
if 'uniquecstrholder' in asession.transaction_data: |
4490
d45cde54d464
backport stable branch and some vreg cleanups:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4307
diff
changeset
|
40 |
return |
d45cde54d464
backport stable branch and some vreg cleanups:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4307
diff
changeset
|
41 |
_UNIQUE_CONSTRAINTS_LOCK.acquire() |
4517
0f3c10fc42b2
backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4498
diff
changeset
|
42 |
asession.transaction_data['uniquecstrholder'] = True |
4490
d45cde54d464
backport stable branch and some vreg cleanups:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4307
diff
changeset
|
43 |
# register operation responsible to release the lock on commit/rollback |
4530
a3c1549a68c6
fix name error introduced by bad merging of stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4517
diff
changeset
|
44 |
_ReleaseUniqueConstraintsOperation(asession) |
4490
d45cde54d464
backport stable branch and some vreg cleanups:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4307
diff
changeset
|
45 |
|
d45cde54d464
backport stable branch and some vreg cleanups:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4307
diff
changeset
|
46 |
def _release_unique_cstr_lock(session): |
4517
0f3c10fc42b2
backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4498
diff
changeset
|
47 |
if 'uniquecstrholder' in session.transaction_data: |
0f3c10fc42b2
backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4498
diff
changeset
|
48 |
del session.transaction_data['uniquecstrholder'] |
4490
d45cde54d464
backport stable branch and some vreg cleanups:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4307
diff
changeset
|
49 |
_UNIQUE_CONSTRAINTS_LOCK.release() |
d45cde54d464
backport stable branch and some vreg cleanups:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4307
diff
changeset
|
50 |
|
d45cde54d464
backport stable branch and some vreg cleanups:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4307
diff
changeset
|
51 |
class _ReleaseUniqueConstraintsOperation(hook.Operation): |
d45cde54d464
backport stable branch and some vreg cleanups:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4307
diff
changeset
|
52 |
def commit_event(self): |
d45cde54d464
backport stable branch and some vreg cleanups:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4307
diff
changeset
|
53 |
pass |
d45cde54d464
backport stable branch and some vreg cleanups:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4307
diff
changeset
|
54 |
def postcommit_event(self): |
d45cde54d464
backport stable branch and some vreg cleanups:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4307
diff
changeset
|
55 |
_release_unique_cstr_lock(self.session) |
d45cde54d464
backport stable branch and some vreg cleanups:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4307
diff
changeset
|
56 |
def rollback_event(self): |
d45cde54d464
backport stable branch and some vreg cleanups:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4307
diff
changeset
|
57 |
_release_unique_cstr_lock(self.session) |
d45cde54d464
backport stable branch and some vreg cleanups:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4307
diff
changeset
|
58 |
|
2835
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
59 |
|
2841
107ba1c45227
rewrite hooks in sobjects as new Hook style into hooks sub-package
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2835
diff
changeset
|
60 |
class _CheckRequiredRelationOperation(hook.LateOperation): |
2835
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
61 |
"""checking relation cardinality has to be done after commit in |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
62 |
case the relation is being replaced |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
63 |
""" |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
64 |
eid, rtype = None, None |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
65 |
|
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
66 |
def precommit_event(self): |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
67 |
# recheck pending eids |
2841
107ba1c45227
rewrite hooks in sobjects as new Hook style into hooks sub-package
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2835
diff
changeset
|
68 |
if self.session.deleted_in_transaction(self.eid): |
2835
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
69 |
return |
3890
d7a270f50f54
backport stable branch (one more time painfully)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3731
diff
changeset
|
70 |
if self.rtype in self.session.transaction_data.get('pendingrtypes', ()): |
d7a270f50f54
backport stable branch (one more time painfully)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3731
diff
changeset
|
71 |
return |
2835
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
72 |
if self.session.unsafe_execute(*self._rql()).rowcount < 1: |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
73 |
etype = self.session.describe(self.eid)[0] |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
74 |
_ = self.session._ |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
75 |
msg = _('at least one relation %(rtype)s is required on %(etype)s (%(eid)s)') |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
76 |
msg %= {'rtype': _(self.rtype), 'etype': _(etype), 'eid': self.eid} |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
77 |
raise ValidationError(self.eid, {self.rtype: msg}) |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
78 |
|
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
79 |
def commit_event(self): |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
80 |
pass |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
81 |
|
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
82 |
def _rql(self): |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
83 |
raise NotImplementedError() |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
84 |
|
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
85 |
|
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
86 |
class _CheckSRelationOp(_CheckRequiredRelationOperation): |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
87 |
"""check required subject relation""" |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
88 |
def _rql(self): |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
89 |
return 'Any O WHERE S eid %%(x)s, S %s O' % self.rtype, {'x': self.eid}, 'x' |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
90 |
|
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
91 |
|
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
92 |
class _CheckORelationOp(_CheckRequiredRelationOperation): |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
93 |
"""check required object relation""" |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
94 |
def _rql(self): |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
95 |
return 'Any S WHERE O eid %%(x)s, S %s O' % self.rtype, {'x': self.eid}, 'x' |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
96 |
|
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
97 |
|
2841
107ba1c45227
rewrite hooks in sobjects as new Hook style into hooks sub-package
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2835
diff
changeset
|
98 |
class IntegrityHook(hook.Hook): |
107ba1c45227
rewrite hooks in sobjects as new Hook style into hooks sub-package
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2835
diff
changeset
|
99 |
__abstract__ = True |
107ba1c45227
rewrite hooks in sobjects as new Hook style into hooks sub-package
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2835
diff
changeset
|
100 |
category = 'integrity' |
107ba1c45227
rewrite hooks in sobjects as new Hook style into hooks sub-package
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2835
diff
changeset
|
101 |
|
3720
5376aaadd16b
backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3646
diff
changeset
|
102 |
class UserIntegrityHook(IntegrityHook): |
3731
d4af295515c0
mark class as abstract
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3728
diff
changeset
|
103 |
__abstract__ = True |
4027 | 104 |
__select__ = IntegrityHook.__select__ & hook.regular_session() |
2841
107ba1c45227
rewrite hooks in sobjects as new Hook style into hooks sub-package
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2835
diff
changeset
|
105 |
|
3720
5376aaadd16b
backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3646
diff
changeset
|
106 |
|
5376aaadd16b
backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3646
diff
changeset
|
107 |
class CheckCardinalityHook(UserIntegrityHook): |
2835
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
108 |
"""check cardinalities are satisfied""" |
3376
f5c69485381f
[appobjects] use __regid__ instead of __id__, more explicit
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3086
diff
changeset
|
109 |
__regid__ = 'checkcard' |
2835
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
110 |
events = ('after_add_entity', 'before_delete_relation') |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
111 |
|
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
112 |
def __call__(self): |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
113 |
getattr(self, self.event)() |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
114 |
|
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
115 |
def checkrel_if_necessary(self, opcls, rtype, eid): |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
116 |
"""check an equivalent operation has not already been added""" |
2847
c2ee28f4d4b1
use ._cw instead of .cw_req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2841
diff
changeset
|
117 |
for op in self._cw.pending_operations: |
2835
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
118 |
if isinstance(op, opcls) and op.rtype == rtype and op.eid == eid: |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
119 |
break |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
120 |
else: |
2847
c2ee28f4d4b1
use ._cw instead of .cw_req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2841
diff
changeset
|
121 |
opcls(self._cw, rtype=rtype, eid=eid) |
2835
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
122 |
|
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
123 |
def after_add_entity(self): |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
124 |
eid = self.entity.eid |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
125 |
eschema = self.entity.e_schema |
3890
d7a270f50f54
backport stable branch (one more time painfully)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3731
diff
changeset
|
126 |
for rschema, targetschemas, role in eschema.relation_definitions(): |
2835
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
127 |
# skip automatically handled relations |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
128 |
if rschema.type in DONT_CHECK_RTYPES_ON_ADD: |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
129 |
continue |
3894
27cbf98ad863
forgotten stuff
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3890
diff
changeset
|
130 |
opcls = role == 'subject' and _CheckSRelationOp or _CheckORelationOp |
3890
d7a270f50f54
backport stable branch (one more time painfully)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3731
diff
changeset
|
131 |
rdef = rschema.role_rdef(eschema, targetschemas[0], role) |
d7a270f50f54
backport stable branch (one more time painfully)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3731
diff
changeset
|
132 |
if rdef.role_cardinality(role) in '1+': |
2835
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
133 |
self.checkrel_if_necessary(opcls, rschema.type, eid) |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
134 |
|
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
135 |
def before_delete_relation(self): |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
136 |
rtype = self.rtype |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
137 |
if rtype in DONT_CHECK_RTYPES_ON_DEL: |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
138 |
return |
2847
c2ee28f4d4b1
use ._cw instead of .cw_req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2841
diff
changeset
|
139 |
session = self._cw |
2835
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
140 |
eidfrom, eidto = self.eidfrom, self.eidto |
2841
107ba1c45227
rewrite hooks in sobjects as new Hook style into hooks sub-package
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2835
diff
changeset
|
141 |
card = session.schema_rproperty(rtype, eidfrom, eidto, 'cardinality') |
2835
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
142 |
pendingrdefs = session.transaction_data.get('pendingrdefs', ()) |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
143 |
if (session.describe(eidfrom)[0], rtype, session.describe(eidto)[0]) in pendingrdefs: |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
144 |
return |
2841
107ba1c45227
rewrite hooks in sobjects as new Hook style into hooks sub-package
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2835
diff
changeset
|
145 |
if card[0] in '1+' and not session.deleted_in_transaction(eidfrom): |
2835
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
146 |
self.checkrel_if_necessary(_CheckSRelationOp, rtype, eidfrom) |
2841
107ba1c45227
rewrite hooks in sobjects as new Hook style into hooks sub-package
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2835
diff
changeset
|
147 |
if card[1] in '1+' and not session.deleted_in_transaction(eidto): |
2835
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
148 |
self.checkrel_if_necessary(_CheckORelationOp, rtype, eidto) |
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 |
|
2841
107ba1c45227
rewrite hooks in sobjects as new Hook style into hooks sub-package
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2835
diff
changeset
|
151 |
class _CheckConstraintsOp(hook.LateOperation): |
2835
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
152 |
"""check a new relation satisfy its constraints |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
153 |
""" |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
154 |
def precommit_event(self): |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
155 |
eidfrom, rtype, eidto = self.rdef |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
156 |
# first check related entities have not been deleted in the same |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
157 |
# transaction |
2841
107ba1c45227
rewrite hooks in sobjects as new Hook style into hooks sub-package
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2835
diff
changeset
|
158 |
if self.session.deleted_in_transaction(eidfrom): |
2835
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
159 |
return |
2841
107ba1c45227
rewrite hooks in sobjects as new Hook style into hooks sub-package
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2835
diff
changeset
|
160 |
if self.session.deleted_in_transaction(eidto): |
2835
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
161 |
return |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
162 |
for constraint in self.constraints: |
4490
d45cde54d464
backport stable branch and some vreg cleanups:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4307
diff
changeset
|
163 |
# XXX |
d45cde54d464
backport stable branch and some vreg cleanups:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4307
diff
changeset
|
164 |
# * lock RQLConstraint as well? |
d45cde54d464
backport stable branch and some vreg cleanups:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4307
diff
changeset
|
165 |
# * use a constraint id to use per constraint lock and avoid |
d45cde54d464
backport stable branch and some vreg cleanups:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4307
diff
changeset
|
166 |
# unnecessary commit serialization ? |
d45cde54d464
backport stable branch and some vreg cleanups:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4307
diff
changeset
|
167 |
if isinstance(constraint, RQLUniqueConstraint): |
d45cde54d464
backport stable branch and some vreg cleanups:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4307
diff
changeset
|
168 |
_acquire_unique_cstr_lock(self.session) |
2835
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
169 |
try: |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
170 |
constraint.repo_check(self.session, eidfrom, rtype, eidto) |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
171 |
except NotImplementedError: |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
172 |
self.critical('can\'t check constraint %s, not supported', |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
173 |
constraint) |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
174 |
|
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
175 |
def commit_event(self): |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
176 |
pass |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
177 |
|
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
178 |
|
3720
5376aaadd16b
backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3646
diff
changeset
|
179 |
class CheckConstraintHook(UserIntegrityHook): |
2835
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
180 |
"""check the relation satisfy its constraints |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
181 |
|
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
182 |
this is delayed to a precommit time operation since other relation which |
3630
275feb5370c9
oops, feature killed by merge...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3590
diff
changeset
|
183 |
will make constraint satisfied (or unsatisfied) may be added later. |
2835
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
184 |
""" |
3376
f5c69485381f
[appobjects] use __regid__ instead of __id__, more explicit
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3086
diff
changeset
|
185 |
__regid__ = 'checkconstraint' |
2835
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
186 |
events = ('after_add_relation',) |
2841
107ba1c45227
rewrite hooks in sobjects as new Hook style into hooks sub-package
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2835
diff
changeset
|
187 |
|
2835
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
188 |
def __call__(self): |
3998
94cc7cad3d2d
backport stable into default
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3894
diff
changeset
|
189 |
# XXX get only RQL[Unique]Constraints? |
2847
c2ee28f4d4b1
use ._cw instead of .cw_req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2841
diff
changeset
|
190 |
constraints = self._cw.schema_rproperty(self.rtype, self.eidfrom, self.eidto, |
3630
275feb5370c9
oops, feature killed by merge...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3590
diff
changeset
|
191 |
'constraints') |
2835
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
192 |
if constraints: |
2847
c2ee28f4d4b1
use ._cw instead of .cw_req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2841
diff
changeset
|
193 |
_CheckConstraintsOp(self._cw, constraints=constraints, |
2835
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
194 |
rdef=(self.eidfrom, self.rtype, self.eidto)) |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
195 |
|
4027 | 196 |
|
3720
5376aaadd16b
backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3646
diff
changeset
|
197 |
class CheckAttributeConstraintHook(UserIntegrityHook): |
3630
275feb5370c9
oops, feature killed by merge...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3590
diff
changeset
|
198 |
"""check the attribute relation satisfy its constraints |
275feb5370c9
oops, feature killed by merge...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3590
diff
changeset
|
199 |
|
275feb5370c9
oops, feature killed by merge...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3590
diff
changeset
|
200 |
this is delayed to a precommit time operation since other relation which |
275feb5370c9
oops, feature killed by merge...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3590
diff
changeset
|
201 |
will make constraint satisfied (or unsatisfied) may be added later. |
275feb5370c9
oops, feature killed by merge...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3590
diff
changeset
|
202 |
""" |
275feb5370c9
oops, feature killed by merge...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3590
diff
changeset
|
203 |
__regid__ = 'checkattrconstraint' |
275feb5370c9
oops, feature killed by merge...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3590
diff
changeset
|
204 |
events = ('after_add_entity', 'after_update_entity') |
275feb5370c9
oops, feature killed by merge...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3590
diff
changeset
|
205 |
|
275feb5370c9
oops, feature killed by merge...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3590
diff
changeset
|
206 |
def __call__(self): |
4190
742e3eb16f81
fix bad merge
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4181
diff
changeset
|
207 |
eschema = self.entity.e_schema |
4181
c79135c217df
backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4075
diff
changeset
|
208 |
for attr in self.entity.edited_attributes: |
c79135c217df
backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4075
diff
changeset
|
209 |
if eschema.subjrels[attr].final: |
c79135c217df
backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4075
diff
changeset
|
210 |
constraints = [c for c in eschema.rdef(attr).constraints |
3998
94cc7cad3d2d
backport stable into default
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3894
diff
changeset
|
211 |
if isinstance(c, (RQLUniqueConstraint, RQLConstraint))] |
3630
275feb5370c9
oops, feature killed by merge...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3590
diff
changeset
|
212 |
if constraints: |
275feb5370c9
oops, feature killed by merge...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3590
diff
changeset
|
213 |
_CheckConstraintsOp(self._cw, constraints=constraints, |
4181
c79135c217df
backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4075
diff
changeset
|
214 |
rdef=(self.entity.eid, attr, None)) |
3630
275feb5370c9
oops, feature killed by merge...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3590
diff
changeset
|
215 |
|
2841
107ba1c45227
rewrite hooks in sobjects as new Hook style into hooks sub-package
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2835
diff
changeset
|
216 |
|
3720
5376aaadd16b
backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3646
diff
changeset
|
217 |
class CheckUniqueHook(UserIntegrityHook): |
3376
f5c69485381f
[appobjects] use __regid__ instead of __id__, more explicit
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3086
diff
changeset
|
218 |
__regid__ = 'checkunique' |
2835
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
219 |
events = ('before_add_entity', 'before_update_entity') |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
220 |
|
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
221 |
def __call__(self): |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
222 |
entity = self.entity |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
223 |
eschema = entity.e_schema |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
224 |
for attr in entity.edited_attributes: |
4024
6a14cff373c3
more api update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4023
diff
changeset
|
225 |
if eschema.subjrels[attr].final and eschema.has_unique_values(attr): |
3086
94ed8f0f0d14
only get value when necessary to check uniqueness
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2968
diff
changeset
|
226 |
val = entity[attr] |
94ed8f0f0d14
only get value when necessary to check uniqueness
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2968
diff
changeset
|
227 |
if val is None: |
94ed8f0f0d14
only get value when necessary to check uniqueness
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2968
diff
changeset
|
228 |
continue |
2835
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
229 |
rql = '%s X WHERE X %s %%(val)s' % (entity.e_schema, attr) |
2847
c2ee28f4d4b1
use ._cw instead of .cw_req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2841
diff
changeset
|
230 |
rset = self._cw.unsafe_execute(rql, {'val': val}) |
2835
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
231 |
if rset and rset[0][0] != entity.eid: |
2847
c2ee28f4d4b1
use ._cw instead of .cw_req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2841
diff
changeset
|
232 |
msg = self._cw._('the value "%s" is already used, use another one') |
2835
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
233 |
raise ValidationError(entity.eid, {attr: msg % val}) |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
234 |
|
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
235 |
|
2841
107ba1c45227
rewrite hooks in sobjects as new Hook style into hooks sub-package
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2835
diff
changeset
|
236 |
class _DelayedDeleteOp(hook.Operation): |
2835
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
237 |
"""delete the object of composite relation except if the relation |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
238 |
has actually been redirected to another composite |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
239 |
""" |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
240 |
|
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
241 |
def precommit_event(self): |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
242 |
session = self.session |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
243 |
# don't do anything if the entity is being created or deleted |
2841
107ba1c45227
rewrite hooks in sobjects as new Hook style into hooks sub-package
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2835
diff
changeset
|
244 |
if not (session.deleted_in_transaction(self.eid) or |
107ba1c45227
rewrite hooks in sobjects as new Hook style into hooks sub-package
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2835
diff
changeset
|
245 |
session.added_in_transaction(self.eid)): |
2835
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
246 |
etype = session.describe(self.eid)[0] |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
247 |
session.unsafe_execute('DELETE %s X WHERE X eid %%(x)s, NOT %s' |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
248 |
% (etype, self.relation), |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
249 |
{'x': self.eid}, 'x') |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
250 |
|
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
251 |
|
2841
107ba1c45227
rewrite hooks in sobjects as new Hook style into hooks sub-package
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2835
diff
changeset
|
252 |
class DeleteCompositeOrphanHook(IntegrityHook): |
2835
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
253 |
"""delete the composed of a composite relation when this relation is deleted |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
254 |
""" |
3376
f5c69485381f
[appobjects] use __regid__ instead of __id__, more explicit
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3086
diff
changeset
|
255 |
__regid__ = 'deletecomposite' |
2835
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
256 |
events = ('before_delete_relation',) |
2841
107ba1c45227
rewrite hooks in sobjects as new Hook style into hooks sub-package
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2835
diff
changeset
|
257 |
|
2835
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
258 |
def __call__(self): |
3589
a5432f99f2d9
backport stable branch
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3376
diff
changeset
|
259 |
# if the relation is being delete, don't delete composite's components |
a5432f99f2d9
backport stable branch
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3376
diff
changeset
|
260 |
# automatically |
a5432f99f2d9
backport stable branch
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3376
diff
changeset
|
261 |
pendingrdefs = self._cw.transaction_data.get('pendingrdefs', ()) |
3590 | 262 |
if (self._cw.describe(self.eidfrom)[0], self.rtype, |
263 |
self._cw.describe(self.eidto)[0]) in pendingrdefs: |
|
3589
a5432f99f2d9
backport stable branch
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3376
diff
changeset
|
264 |
return |
2847
c2ee28f4d4b1
use ._cw instead of .cw_req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2841
diff
changeset
|
265 |
composite = self._cw.schema_rproperty(self.rtype, self.eidfrom, self.eidto, |
2841
107ba1c45227
rewrite hooks in sobjects as new Hook style into hooks sub-package
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2835
diff
changeset
|
266 |
'composite') |
2835
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
267 |
if composite == 'subject': |
2847
c2ee28f4d4b1
use ._cw instead of .cw_req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2841
diff
changeset
|
268 |
_DelayedDeleteOp(self._cw, eid=self.eidto, |
2835
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
269 |
relation='Y %s X' % self.rtype) |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
270 |
elif composite == 'object': |
2847
c2ee28f4d4b1
use ._cw instead of .cw_req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2841
diff
changeset
|
271 |
_DelayedDeleteOp(self._cw, eid=self.eidfrom, |
2835
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
272 |
relation='X %s Y' % self.rtype) |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
273 |
|
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
274 |
|
2841
107ba1c45227
rewrite hooks in sobjects as new Hook style into hooks sub-package
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2835
diff
changeset
|
275 |
class DontRemoveOwnersGroupHook(IntegrityHook): |
2835
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
276 |
"""delete the composed of a composite relation when this relation is deleted |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
277 |
""" |
3376
f5c69485381f
[appobjects] use __regid__ instead of __id__, more explicit
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3086
diff
changeset
|
278 |
__regid__ = 'checkownersgroup' |
4075
e710f4052bd6
use implements instead of entity_implements
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4027
diff
changeset
|
279 |
__select__ = IntegrityHook.__select__ & implements('CWGroup') |
2835
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
280 |
events = ('before_delete_entity', 'before_update_entity') |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
281 |
|
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
282 |
def __call__(self): |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
283 |
if self.event == 'before_delete_entity' and self.entity.name == 'owners': |
2847
c2ee28f4d4b1
use ._cw instead of .cw_req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2841
diff
changeset
|
284 |
raise ValidationError(self.entity.eid, {None: self._cw._('can\'t be deleted')}) |
2896 | 285 |
elif self.event == 'before_update_entity' and 'name' in self.entity.edited_attributes: |
2835
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
286 |
newname = self.entity.pop('name') |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
287 |
oldname = self.entity.name |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
288 |
if oldname == 'owners' and newname != oldname: |
2847
c2ee28f4d4b1
use ._cw instead of .cw_req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2841
diff
changeset
|
289 |
raise ValidationError(self.entity.eid, {'name': self._cw._('can\'t be changed')}) |
2835
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
290 |
self.entity['name'] = newname |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
291 |
|
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
292 |
|
3720
5376aaadd16b
backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3646
diff
changeset
|
293 |
class TidyHtmlFields(UserIntegrityHook): |
2841
107ba1c45227
rewrite hooks in sobjects as new Hook style into hooks sub-package
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2835
diff
changeset
|
294 |
"""tidy HTML in rich text strings""" |
3376
f5c69485381f
[appobjects] use __regid__ instead of __id__, more explicit
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3086
diff
changeset
|
295 |
__regid__ = 'htmltidy' |
2841
107ba1c45227
rewrite hooks in sobjects as new Hook style into hooks sub-package
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2835
diff
changeset
|
296 |
events = ('before_add_entity', 'before_update_entity') |
107ba1c45227
rewrite hooks in sobjects as new Hook style into hooks sub-package
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2835
diff
changeset
|
297 |
|
107ba1c45227
rewrite hooks in sobjects as new Hook style into hooks sub-package
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2835
diff
changeset
|
298 |
def __call__(self): |
107ba1c45227
rewrite hooks in sobjects as new Hook style into hooks sub-package
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2835
diff
changeset
|
299 |
entity = self.entity |
107ba1c45227
rewrite hooks in sobjects as new Hook style into hooks sub-package
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2835
diff
changeset
|
300 |
metaattrs = entity.e_schema.meta_attributes() |
107ba1c45227
rewrite hooks in sobjects as new Hook style into hooks sub-package
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2835
diff
changeset
|
301 |
for metaattr, (metadata, attr) in metaattrs.iteritems(): |
107ba1c45227
rewrite hooks in sobjects as new Hook style into hooks sub-package
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2835
diff
changeset
|
302 |
if metadata == 'format' and attr in entity.edited_attributes: |
107ba1c45227
rewrite hooks in sobjects as new Hook style into hooks sub-package
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2835
diff
changeset
|
303 |
try: |
107ba1c45227
rewrite hooks in sobjects as new Hook style into hooks sub-package
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2835
diff
changeset
|
304 |
value = entity[attr] |
107ba1c45227
rewrite hooks in sobjects as new Hook style into hooks sub-package
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2835
diff
changeset
|
305 |
except KeyError: |
107ba1c45227
rewrite hooks in sobjects as new Hook style into hooks sub-package
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2835
diff
changeset
|
306 |
continue # no text to tidy |
107ba1c45227
rewrite hooks in sobjects as new Hook style into hooks sub-package
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2835
diff
changeset
|
307 |
if isinstance(value, unicode): # filter out None and Binary |
107ba1c45227
rewrite hooks in sobjects as new Hook style into hooks sub-package
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2835
diff
changeset
|
308 |
if getattr(entity, str(metaattr)) == 'text/html': |
2847
c2ee28f4d4b1
use ._cw instead of .cw_req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2841
diff
changeset
|
309 |
entity[attr] = soup2xhtml(value, self._cw.encoding) |
2841
107ba1c45227
rewrite hooks in sobjects as new Hook style into hooks sub-package
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2835
diff
changeset
|
310 |
|
107ba1c45227
rewrite hooks in sobjects as new Hook style into hooks sub-package
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2835
diff
changeset
|
311 |
|
107ba1c45227
rewrite hooks in sobjects as new Hook style into hooks sub-package
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2835
diff
changeset
|
312 |
class StripCWUserLoginHook(IntegrityHook): |
107ba1c45227
rewrite hooks in sobjects as new Hook style into hooks sub-package
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2835
diff
changeset
|
313 |
"""ensure user logins are stripped""" |
3376
f5c69485381f
[appobjects] use __regid__ instead of __id__, more explicit
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3086
diff
changeset
|
314 |
__regid__ = 'stripuserlogin' |
4075
e710f4052bd6
use implements instead of entity_implements
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4027
diff
changeset
|
315 |
__select__ = IntegrityHook.__select__ & implements('CWUser') |
2841
107ba1c45227
rewrite hooks in sobjects as new Hook style into hooks sub-package
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2835
diff
changeset
|
316 |
events = ('before_add_entity', 'before_update_entity',) |
107ba1c45227
rewrite hooks in sobjects as new Hook style into hooks sub-package
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2835
diff
changeset
|
317 |
|
2900 | 318 |
def __call__(self): |
319 |
user = self.entity |
|
320 |
if 'login' in user.edited_attributes and user.login: |
|
2968
0e3460341023
somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2901
diff
changeset
|
321 |
user.login = user.login.strip() |