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
--- 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]