--- a/server/hook.py Tue Sep 14 08:48:44 2010 +0200
+++ b/server/hook.py Thu Sep 16 18:56:35 2010 +0200
@@ -248,7 +248,7 @@
from itertools import chain
from logilab.common.decorators import classproperty
-from logilab.common.deprecation import deprecated
+from logilab.common.deprecation import deprecated, class_renamed
from logilab.common.logging_ext import set_log_methods
from cubicweb import RegistryNotFound
@@ -480,15 +480,19 @@
set_log_methods(Hook, getLogger('cubicweb.hook'))
-# base classes for relation propagation ########################################
+# abtract hooks for relation propagation #######################################
+# See example usage in hooks of the nosylist cube
-class PropagateSubjectRelationHook(Hook):
+class PropagateRelationHook(Hook):
"""propagate some `main_rtype` relation on entities linked as object of
`subject_relations` or as subject of `object_relations` (the watched
relations).
This hook ensure that when one of the watched relation is added, the
`main_rtype` relation is added to the target entity of the relation.
+
+ You usually want to use the :class:`match_rtype_sets` selector on concret
+ classes.
"""
events = ('after_add_relation',)
@@ -514,56 +518,77 @@
{'x': meid, 'e': seid})
-class PropagateSubjectRelationAddHook(Hook):
- """propagate to entities at the end of watched relations when a `main_rtype`
- relation is added
+class PropagateRelationAddHook(Hook):
+ """Propagate to entities at the end of watched relations when a `main_rtype`
+ relation is added.
+
+ `subject_relations` and `object_relations` attributes should be specified on
+ subclasses and are usually shared references with attributes of the same
+ name on :class:`PropagateRelationHook`.
+
+ Because of those shared references, you can use `skip_subject_relations` and
+ `skip_object_relations` attributes when you don't want to propagate to
+ entities linked through some particular relations.
"""
events = ('after_add_relation',)
- # to set in concrete class
+ # to set in concrete class (mandatory)
subject_relations = None
object_relations = None
+ # to set in concrete class (optionaly)
+ skip_subject_relations = ()
+ skip_object_relations = ()
def __call__(self):
eschema = self._cw.vreg.schema.eschema(self._cw.describe(self.eidfrom)[0])
execute = self._cw.execute
for rel in self.subject_relations:
- if rel in eschema.subjrels:
+ if rel in eschema.subjrels and not rel in self.skip_subject_relations:
execute('SET R %s P WHERE X eid %%(x)s, P eid %%(p)s, '
'X %s R, NOT R %s P' % (self.rtype, rel, self.rtype),
{'x': self.eidfrom, 'p': self.eidto})
for rel in self.object_relations:
- if rel in eschema.objrels:
+ if rel in eschema.objrels and not rel in self.skip_object_relations:
execute('SET R %s P WHERE X eid %%(x)s, P eid %%(p)s, '
'R %s X, NOT R %s P' % (self.rtype, rel, self.rtype),
{'x': self.eidfrom, 'p': self.eidto})
-class PropagateSubjectRelationDelHook(Hook):
- """propagate to entities at the end of watched relations when a `main_rtype`
- relation is deleted
+class PropagateRelationDelHook(PropagateRelationAddHook):
+ """Propagate to entities at the end of watched relations when a `main_rtype`
+ relation is deleted.
+
+ This is the opposite of the :class:`PropagateRelationAddHook`, see its
+ documentation for how to use this class.
"""
events = ('after_delete_relation',)
- # to set in concrete class
- subject_relations = None
- object_relations = None
-
def __call__(self):
eschema = self._cw.vreg.schema.eschema(self._cw.describe(self.eidfrom)[0])
execute = self._cw.execute
for rel in self.subject_relations:
- if rel in eschema.subjrels:
+ if rel in eschema.subjrels and not rel in self.skip_subject_relations:
execute('DELETE R %s P WHERE X eid %%(x)s, P eid %%(p)s, '
'X %s R' % (self.rtype, rel),
{'x': self.eidfrom, 'p': self.eidto})
for rel in self.object_relations:
- if rel in eschema.objrels:
+ if rel in eschema.objrels and not rel in self.skip_object_relations:
execute('DELETE R %s P WHERE X eid %%(x)s, P eid %%(p)s, '
'R %s X' % (self.rtype, rel),
{'x': self.eidfrom, 'p': self.eidto})
+PropagateSubjectRelationHook = class_renamed(
+ 'PropagateSubjectRelationHook', PropagateRelationHook,
+ '[3.9] PropagateSubjectRelationHook has been renamed to PropagateRelationHook')
+PropagateSubjectRelationAddHook = class_renamed(
+ 'PropagateSubjectRelationAddHook', PropagateRelationAddHook,
+ '[3.9] PropagateSubjectRelationAddHook has been renamed to PropagateRelationAddHook')
+PropagateSubjectRelationDelHook = class_renamed(
+ 'PropagateSubjectRelationDelHook', PropagateRelationDelHook,
+ '[3.9] PropagateSubjectRelationDelHook has been renamed to PropagateRelationDelHook')
+
+
# abstract classes for operation ###############################################
class Operation(object):