[selectors, facet] make is_instance and other EClassSelector subclass gather entity classes from 'select' and 'filtered_variable' context information. Closes #1796732
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Fri, 01 Jul 2011 18:42:36 +0200
changeset 7610 838a0c910bb5
parent 7609 fbefd1b9e587
child 7612 bfd4ee0d43ac
[selectors, facet] make is_instance and other EClassSelector subclass gather entity classes from 'select' and 'filtered_variable' context information. Closes #1796732 This allow for instance to use the filter form on rqlst where the filtered variable is not selected
selectors.py
web/views/facets.py
--- a/selectors.py	Fri Jul 01 16:20:57 2011 +0200
+++ b/selectors.py	Fri Jul 01 18:42:36 2011 +0200
@@ -255,12 +255,19 @@
 
     * if `entity` is specified, return score for this entity's class
 
-    * elif `row` is specified, return score for the class of the entity
-      found in the specified cell, using column specified by `col` or 0
+    * elif `rset`, `select` and `filtered_variable` are specified, return score
+      for the possible classes for variable in the given rql :class:`Select`
+      node
+
+    * elif `rset` and `row` are specified, return score for the class of the
+      entity found in the specified cell, using column specified by `col` or 0
 
-    * else return the sum of scores for each entity class found in the column
-      specified specified by the `col` argument or in column 0 if not specified,
-      unless:
+    * elif `rset` is specified return score for each entity class found in the
+      column specified specified by the `col` argument or in column 0 if not
+      specified
+
+    When there are several classes to be evaluated, return the sum of scores for
+    each entity class unless:
 
       - `once_is_enough` is False (the default) and some entity class is scored
         to 0, in which case 0 is returned
@@ -276,32 +283,37 @@
         self.accept_none = accept_none
 
     @lltrace
-    def __call__(self, cls, req, rset=None, row=None, col=0, accept_none=None,
+    def __call__(self, cls, req, rset=None, row=None, col=0, entity=None,
+                 select=None, filtered_variable=None,
+                 accept_none=None,
                  **kwargs):
-        if kwargs.get('entity'):
-            return self.score_class(kwargs['entity'].__class__, req)
+        if entity is not None:
+            return self.score_class(entity.__class__, req)
         if not rset:
             return 0
-        score = 0
-        if row is None:
+        if select is not None and filtered_variable is not None:
+            etypes = set(sol[filtered_variable.name] for sol in select.solutions)
+        elif row is None:
             if accept_none is None:
                 accept_none = self.accept_none
-            if not accept_none:
-                if any(rset[i][col] is None for i in xrange(len(rset))):
-                    return 0
-            for etype in rset.column_types(col):
-                if etype is None: # outer join
-                    return 0
-                escore = self.score(cls, req, etype)
-                if not escore and not self.once_is_enough:
-                    return 0
-                elif self.once_is_enough:
-                    return escore
-                score += escore
+            if not accept_none and \
+                   any(rset[i][col] is None for i in xrange(len(rset))):
+                return 0
+            etypes = rset.column_types(col)
         else:
             etype = rset.description[row][col]
-            if etype is not None:
-                score = self.score(cls, req, etype)
+            # may have None in rset.description on outer join
+            if etype is None:
+                return 0
+            etypes = (etype,)
+        score = 0
+        for etype in etypes:
+            escore = self.score(cls, req, etype)
+            if not escore and not self.once_is_enough:
+                return 0
+            elif self.once_is_enough:
+                return escore
+            score += escore
         return score
 
     def score(self, cls, req, etype):
--- a/web/views/facets.py	Fri Jul 01 16:20:57 2011 +0200
+++ b/web/views/facets.py	Fri Jul 01 18:42:36 2011 +0200
@@ -198,7 +198,7 @@
 
 class FilterTable(FacetFilterMixIn, AnyRsetView):
     __regid__ = 'facet.filtertable'
-    __select__ = non_final_entity() & has_facets()
+    __select__ = has_facets()
     wdg_stack_size = 8
 
     def call(self, vid, divid, vidargs, cssclass=''):