closes #345410: two_lines_rset, two_cols_rset, two_etypes_rset are badly named
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Thu, 21 Jan 2010 17:38:31 +0100
changeset 4320 4efd4c306746
parent 4319 3b72c7e6149d
child 4321 80b455066c9a
closes #345410: two_lines_rset, two_cols_rset, two_etypes_rset are badly named replaced by multi_lines_rset, multi_columns_rset, multi_etypes_rset, all taking optional 'nb' argument allowing to specify and exact count. Bw compat is kept, usage of deprecated function updated in cw itself. Also drop custom at_least_two_columns selector (in views.plots) since it was the same as multi_columns_rset. Hopefuly the renaming will help in avoid such pb... We should now decide if we want to deprecate one_* selector in favor of multi_*(nb=1). See note on this at then end of selectors.py
selectors.py
web/views/actions.py
web/views/basecomponents.py
web/views/facets.py
web/views/ibreadcrumbs.py
web/views/plots.py
--- a/selectors.py	Thu Jan 21 17:03:30 2010 +0100
+++ b/selectors.py	Thu Jan 21 17:38:31 2010 +0100
@@ -326,21 +326,27 @@
         return 1
     return 0
 
-@objectify_selector
-@lltrace
-def two_lines_rset(cls, req, rset=None, **kwargs):
-    """accept result set with *at least* two lines of result"""
-    if rset is not None and rset.rowcount > 1:
-        return 1
-    return 0
+
+class multi_lines_rset(Selector):
+    def __init__(self, nb=None):
+        self.expected = nb
+
+    def match_expected(self, num):
+        if self.expected is None:
+            return num > 1
+        return num == self.expected
 
-@objectify_selector
-@lltrace
-def two_cols_rset(cls, req, rset=None, **kwargs):
-    """accept result set with at least one line and two columns of result"""
-    if rset is not None and rset.rowcount and len(rset.rows[0]) > 1:
-        return 1
-    return 0
+    @lltrace
+    def __call__(self, cls, req, rset=None, row=None, col=0, **kwargs):
+        return rset is not None and self.match_expected(rset.rowcount)
+
+
+class multi_columns_rset(multi_lines_rset):
+
+    @lltrace
+    def __call__(self, cls, req, rset=None, row=None, col=0, **kwargs):
+        return rset and self.match_expected(len(rset.rows[0]))
+
 
 @objectify_selector
 @lltrace
@@ -384,17 +390,13 @@
         return 0
     return 1
 
-@objectify_selector
-@lltrace
-def two_etypes_rset(cls, req, rset=None, col=0, **kwargs):
-    """accept result set where entities in the specified column (or 0) are not
-    of the same type
-    """
-    if rset:
-        etypes = rset.column_types(col)
-        if len(etypes) > 1:
-            return 1
-    return 0
+
+class multi_etypes_rset(multi_lines_rset):
+
+    @lltrace
+    def __call__(self, cls, req, rset=None, **kwargs):
+        return rset and self.match_expected(len(rset.column_types(col)))
+
 
 class non_final_entity(EClassSelector):
     """accept if entity type found in the result set is non final.
@@ -406,6 +408,7 @@
             return 0
         return 1
 
+
 @objectify_selector
 @lltrace
 def authenticated_user(cls, req, *args, **kwargs):
@@ -965,3 +968,11 @@
         return 1
 
 but_etype = class_renamed('but_etype', _but_etype, 'use ~implements(*etypes) instead')
+
+
+# XXX deprecated the one_* variants of selectors below w/ multi_xxx(nb=1)?
+#     take care at the implementation though (looking for the 'row' argument's
+#     value)
+two_lines_rset = class_renamed('two_lines_rset', multi_lines_rset)
+two_cols_rset = class_renamed('two_cols_rset', multi_columns_rset)
+two_etypes_rset = class_renamed('two_etypes_rset', multi_etypes_rset)
--- a/web/views/actions.py	Thu Jan 21 17:03:30 2010 +0100
+++ b/web/views/actions.py	Thu Jan 21 17:38:31 2010 +0100
@@ -10,7 +10,7 @@
 
 from cubicweb.appobject import objectify_selector
 from cubicweb.selectors import (EntitySelector, yes,
-    one_line_rset, two_lines_rset, one_etype_rset, relation_possible,
+    one_line_rset, multi_lines_rset, one_etype_rset, relation_possible,
     nonempty_rset, non_final_entity,
     authenticated_user, match_user_groups, match_search_state,
     has_permission, has_add_permission,
@@ -139,7 +139,7 @@
 
 class MultipleEditAction(action.Action):
     __regid__ = 'muledit' # XXX get strange conflicts if id='edit'
-    __select__ = (action.Action.__select__ & two_lines_rset() &
+    __select__ = (action.Action.__select__ & multi_lines_rset() &
                   one_etype_rset() & has_permission('update'))
 
     title = _('modify')
@@ -210,7 +210,7 @@
     __regid__ = 'addentity'
     __select__ = (action.Action.__select__ &
                   (addable_etype_empty_rset()
-                   | (two_lines_rset() & one_etype_rset & has_add_permission()))
+                   | (multi_lines_rset() & one_etype_rset & has_add_permission()))
                   )
 
     category = 'moreactions'
--- a/web/views/basecomponents.py	Thu Jan 21 17:03:30 2010 +0100
+++ b/web/views/basecomponents.py	Thu Jan 21 17:38:31 2010 +0100
@@ -15,7 +15,7 @@
 from logilab.mtconverter import xml_escape
 from rql import parse
 
-from cubicweb.selectors import yes, two_etypes_rset, match_form_params
+from cubicweb.selectors import yes, multi_etypes_rset, match_form_params
 from cubicweb.schema import display_name
 from cubicweb.uilib import toggle_action
 from cubicweb.web import component
@@ -169,7 +169,7 @@
     to be able to filter accordingly.
     """
     __regid__ = 'etypenavigation'
-    __select__ = two_etypes_rset() | match_form_params('__restrtype', '__restrtypes',
+    __select__ = multi_etypes_rset() | match_form_params('__restrtype', '__restrtypes',
                                                        '__restrrql')
     cw_property_defs = VISIBLE_PROP_DEF
     # don't want user to hide this component using an cwproperty
--- a/web/views/facets.py	Thu Jan 21 17:03:30 2010 +0100
+++ b/web/views/facets.py	Thu Jan 21 17:38:31 2010 +0100
@@ -12,7 +12,7 @@
 from logilab.mtconverter import xml_escape
 
 from cubicweb.appobject import objectify_selector
-from cubicweb.selectors import (non_final_entity, two_lines_rset,
+from cubicweb.selectors import (non_final_entity, multi_lines_rset,
                                 match_context_prop, yes, relation_possible)
 from cubicweb.web.box import BoxTemplate
 from cubicweb.web.facet import (AbstractFacet, FacetStringWidget, RelationFacet,
@@ -30,7 +30,7 @@
 class FilterBox(BoxTemplate):
     """filter results of a query"""
     __regid__ = 'filter_box'
-    __select__ = (((non_final_entity() & two_lines_rset())
+    __select__ = (((non_final_entity() & multi_lines_rset())
                    | contextview_selector()
                    ) & match_context_prop())
     context = 'left'
--- a/web/views/ibreadcrumbs.py	Thu Jan 21 17:03:30 2010 +0100
+++ b/web/views/ibreadcrumbs.py	Thu Jan 21 17:38:31 2010 +0100
@@ -12,7 +12,7 @@
 
 from cubicweb.interfaces import IBreadCrumbs
 from cubicweb.selectors import (one_line_rset, implements, one_etype_rset,
-                                two_lines_rset, any_rset)
+                                multi_lines_rset, any_rset)
 from cubicweb.view import EntityView, Component
 # don't use AnyEntity since this may cause bug with isinstance() due to reloading
 from cubicweb.entity import Entity
@@ -77,7 +77,7 @@
 
 
 class BreadCrumbETypeVComponent(BreadCrumbEntityVComponent):
-    __select__ = two_lines_rset() & one_etype_rset() & \
+    __select__ = multi_lines_rset() & one_etype_rset() & \
                  implements(IBreadCrumbs, accept_none=False)
 
     def render_breadcrumbs(self, contextentity, path):
--- a/web/views/plots.py	Thu Jan 21 17:03:30 2010 +0100
+++ b/web/views/plots.py	Thu Jan 21 17:38:31 2010 +0100
@@ -17,15 +17,10 @@
 
 from cubicweb.utils import make_uid, UStringIO, datetime2ticks
 from cubicweb.appobject import objectify_selector
+from cubicweb.selectors import multi_columns_rset
 from cubicweb.web.views import baseviews
 
 @objectify_selector
-def at_least_two_columns(cls, req, rset=None, *args, **kwargs):
-    if not rset:
-        return 0
-    return len(rset.rows[0]) >= 2
-
-@objectify_selector
 def all_columns_are_numbers(cls, req, rset=None, *args, **kwargs):
     """accept result set with at least one line and two columns of result
     all columns after second must be of numerical types"""
@@ -130,7 +125,7 @@
 class PlotView(baseviews.AnyRsetView):
     __regid__ = 'plot'
     title = _('generic plot')
-    __select__ = at_least_two_columns() & all_columns_are_numbers()
+    __select__ = multi_columns_rset() & all_columns_are_numbers()
     timemode = False
 
     def call(self, width=500, height=400):
@@ -149,7 +144,7 @@
 
 
 class TimeSeriePlotView(PlotView):
-    __select__ = at_least_two_columns() & columns_are_date_then_numbers()
+    __select__ = multi_columns_rset() & columns_are_date_then_numbers()
     timemode = True
 
 
@@ -180,7 +175,7 @@
         __regid__ = 'piechart'
         pieclass = Pie
 
-        __select__ = at_least_two_columns() & second_column_is_number()
+        __select__ = multi_columns_rset() & second_column_is_number()
 
         def _guess_vid(self, row):
             etype = self.cw_rset.description[row][0]