introduce abstract selectors to get rid of the my_selector() contagion tls-sprint
authorAdrien Di Mascio <Adrien.DiMascio@logilab.fr>
Wed, 18 Feb 2009 13:36:28 +0100
branchtls-sprint
changeset 782 01801a10c567
parent 775 ed106bb2dcd3
child 784 33db07c66789
introduce abstract selectors to get rid of the my_selector() contagion
selectors.py
web/action.py
web/box.py
web/facet.py
web/views/tabs.py
--- a/selectors.py	Wed Feb 18 11:50:15 2009 +0100
+++ b/selectors.py	Wed Feb 18 13:36:28 2009 +0100
@@ -114,6 +114,13 @@
 
 
 # abstract selectors ##########################################################
+class AbstractSelectorMixIn(object):
+    """convenience mix-in for selectors that depends on class attributes
+    cf. `cubicweb.web.action.LinkToEntityAction` for instance
+    """
+    def __call__(self, cls, *args, **kwargs):
+        self.concretize(cls)
+        super(AbstractSelectorMixIn, self).__call__(cls, *args, **kwargs)
 
 class EClassSelector(Selector):
     """abstract class for selectors working on the entity classes of the result
@@ -309,6 +316,8 @@
     """accept result set where entities in the specified column (or 0) are all
     of the same type
     """
+    if rset is None:
+        return 0
     if len(rset.column_types(col)) != 1:
         return 0
     return 1
@@ -602,6 +611,15 @@
                 return 0
         return 1
 
+class abstract_relation_possible(AbstractSelectorMixIn, relation_possible):
+    def __init__(self, action='read', once_is_enough=False):
+        super(abstract_relation_possible, self).__init__(None, None, None,
+                                                         action, once_is_enough)
+
+    def concretize(self, cls):
+        self.rtype = cls.rtype
+        self.role = role(cls)
+        self.target_etype = getattr(cls, 'etype', None)
 
 class has_editable_relation(EntitySelector):
     """accept if some relations for an entity found in the result set is
@@ -648,7 +666,15 @@
             return 0
         return 1
 
+class abstract_may_add_relation(AbstractSelectorMixIn, may_add_relation):
+    def __init__(self, once_is_enough=False):
+        super(abstract_may_add_relation, self).__init__(None, None, once_is_enough)
 
+    def concretize(self, cls):
+        self.rtype = cls.rtype
+        self.role = role(cls)
+
+    
 class has_related_entities(EntitySelector):
     """accept if entity found in the result set has some linked entities using
     the specified relation (optionaly filtered according to the specified target
@@ -675,7 +701,16 @@
             return any(x for x, in rset.description if x == self.target_etype)
         return bool(rset)
 
-        
+class abstract_has_related_entities(AbstractSelectorMixIn, has_related_entities):
+    def __init__(self, once_is_enough=False):
+        super(abstract_has_related_entities, self).__init__(None, None,
+                                                            None, once_is_enough)
+    def concretize(self, cls):
+        self.rtype = cls.rtype
+        self.role = role(cls)
+        self.target_etype = getattr(cls, 'etype', None)
+
+
 class has_permission(EntitySelector):
     """accept if user has the permission to do the requested action on a result
     set entity.
--- a/web/action.py	Wed Feb 18 11:50:15 2009 +0100
+++ b/web/action.py	Wed Feb 18 13:36:28 2009 +0100
@@ -6,10 +6,9 @@
 """
 __docformat__ = "restructuredtext en"
 
-from cubicweb import role, target
-from cubicweb.vregistry import objectify_selector
-from cubicweb.selectors import (relation_possible, match_search_state,
-                                one_line_rset, may_add_relation, yes,
+from cubicweb import target
+from cubicweb.selectors import (abstract_relation_possible, match_search_state,
+                                one_line_rset, abstract_may_add_relation, yes,
                                 accepts_compat, condition_compat, deprecate)
 from cubicweb.appobject import AppRsetObject
 from cubicweb.common.registerers import accepts_registerer
@@ -73,15 +72,9 @@
     using .etype, .rtype and .target attributes to check if the
     action apply and if the logged user has access to it
     """
-    @objectify_selector
-    def my_selector(cls, req, rset, row=None, col=0, **kwargs):
-        selector = (match_search_state('normal') & one_line_rset()
-                    & relation_possible(cls.rtype, role(cls), cls.etype,
-                                        action='add')
-                    & may_add_relation(cls.rtype, role(cls)))
-        return selector(cls, req, rset, row, col, **kwargs)
-
-    __select__ = my_selector()
+    __select__ = (match_search_state('normal') & one_line_rset()
+                  & abstract_relation_possible(action='add')
+                  & abstract_may_add_relation())
     registered = accepts_compat(Action.registered)
     
     category = 'addrelated'
--- a/web/box.py	Wed Feb 18 11:50:15 2009 +0100
+++ b/web/box.py	Wed Feb 18 13:36:28 2009 +0100
@@ -10,9 +10,8 @@
 from logilab.mtconverter import html_escape
 
 from cubicweb import Unauthorized, role as get_role
-from cubicweb.vregistry import objectify_selector
 from cubicweb.selectors import (one_line_rset,  primary_view,
-                                match_context_prop, has_related_entities,
+                                match_context_prop, abstract_has_related_entities,
                                 accepts_compat, has_relation_compat, condition_compat)
 from cubicweb.view import Template, ReloadableMixIn
 
@@ -146,12 +145,7 @@
 
 
 class RelatedEntityBoxTemplate(EntityBoxTemplate):
-    # XXX find a way to generalize access to cls.rtype
-    @objectify_selector
-    def my_selector(cls, req, rset, row=None, col=0, **kwargs):
-        return EntityBoxTemplate.__select__ & has_related_entities(cls.rtype)
-
-    __select__ = my_selector
+    __select__ = EntityBoxTemplate.__select__ & abstract_has_related_entities()
 
     def cell_call(self, row, col, **kwargs):
         entity = self.entity(row, col)
--- a/web/facet.py	Wed Feb 18 11:50:15 2009 +0100
+++ b/web/facet.py	Wed Feb 18 13:36:28 2009 +0100
@@ -19,8 +19,7 @@
 from rql import parse, nodes
 
 from cubicweb import Unauthorized, typed_eid
-from cubicweb.vregistry import objectify_selector
-from cubicweb.selectors import match_context_prop, one_has_relation
+from cubicweb.selectors import match_context_prop, abstract_relation_possible
 from cubicweb.appobject import AppRsetObject
 from cubicweb.common.registerers import priority_registerer
 from cubicweb.web.htmlwidgets import HTMLWidget
@@ -334,14 +333,7 @@
 
 
 class RelationFacet(VocabularyFacet):
-    # XXX find a way to generalize access to cls.rtype
-    @objectify_selector
-    def my_selector(cls, req, rset, row=None, col=0, **kwargs):
-        selector = (relation_possible(cls.rtype, role(cls))
-                    & match_context_prop())
-        return selector(cls, req, rset, row, col, **kwargs)
-    
-    __select__ = my_selector()
+    __select__ = abstract_relation_possible() & match_context_prop()
     # class attributes to configure the rel ation facet
     rtype = None
     role = 'subject' 
--- a/web/views/tabs.py	Wed Feb 18 11:50:15 2009 +0100
+++ b/web/views/tabs.py	Wed Feb 18 13:36:28 2009 +0100
@@ -11,8 +11,7 @@
 from logilab.mtconverter import html_escape
 
 from cubicweb import NoSelectableObject, role
-from cubicweb.vregistry import objectify_selector
-from cubicweb.selectors import has_related_entities
+from cubicweb.selectors import abstract_has_related_entities
 from cubicweb.common.view import EntityView
 from cubicweb.common.utils import HTMLHead
 from cubicweb.common.uilib import rql_for_eid
@@ -144,14 +143,8 @@
     class ProjectScreenshotTab(DataDependantTab, ProjectScreenshotsView):
         id = 'screenshots_tab'
     """
-    # XXX needs to be generalized
-    @objectify_selector
-    def my_selector(cls, req, rset, row=None, col=0, **kwargs):
-        selector = (EntityView.__select__ &
-                    has_related_entities(cls.rtype, role(cls)))
-        return selector(cls, req, rset, row=None, col=0, **kwargs)
-
-    __select__ = my_selector()
+    __select__ = EntityView.__select__ & abstract_has_related_entities()
+                                                          
     vid = 'list'
 
     def cell_call(self, row, col):