# HG changeset patch # User Julien Jehannet # Date 1285328473 -7200 # Node ID f5bd501628b0e9126eaa62380700bcd9d54e8d08 # Parent ef47a2100c6654f6bb4d58f9689ceaf5bfe58311 [selectors] multi_lines_rset selector supports now optional operator for richer comparaisons diff -r ef47a2100c66 -r f5bd501628b0 selectors.py --- a/selectors.py Fri Sep 24 15:00:08 2010 +0200 +++ b/selectors.py Fri Sep 24 13:41:13 2010 +0200 @@ -194,6 +194,7 @@ import logging from warnings import warn +from operator import eq from logilab.common.deprecation import class_renamed from logilab.common.compat import all, any @@ -530,17 +531,26 @@ class multi_lines_rset(Selector): - """If `nb` is specified, return 1 if the result set has exactly `nb` row of - result. Else (`nb` is None), return 1 if the result set contains *at least* + """Return 1 if the operator expression matches between `num` elements + in the result set and the `expected` value if defined. + + By default, multi_lines_rset(expected) matches equality expression: + `nb` row(s) in result set equals to expected value + But, you can perform richer comparisons by overriding default operator: + multi_lines_rset(expected, operator.gt) + + If `expected` is None, return 1 if the result set contains *at least* two rows. + If rset is None, return 0. """ - def __init__(self, nb=None): - self.expected = nb + def __init__(self, expected=None, operator=eq): + self.expected = expected + self.operator = operator def match_expected(self, num): if self.expected is None: return num > 1 - return num == self.expected + return self.operator(num, self.expected) @lltrace def __call__(self, cls, req, rset=None, **kwargs): diff -r ef47a2100c66 -r f5bd501628b0 test/unittest_selectors.py --- a/test/unittest_selectors.py Fri Sep 24 15:00:08 2010 +0200 +++ b/test/unittest_selectors.py Fri Sep 24 13:41:13 2010 +0200 @@ -17,12 +17,14 @@ # with CubicWeb. If not, see . """unit tests for selectors mechanism""" +from operator import eq, lt, le, gt from logilab.common.testlib import TestCase, unittest_main from cubicweb import Binary from cubicweb.devtools.testlib import CubicWebTC from cubicweb.appobject import Selector, AndSelector, OrSelector -from cubicweb.selectors import is_instance, adaptable, match_user_groups +from cubicweb.selectors import (is_instance, adaptable, match_user_groups, + multi_lines_rset) from cubicweb.interfaces import IDownloadable from cubicweb.web import action @@ -190,6 +192,59 @@ finally: del self.vreg[SomeAction.__registry__][SomeAction.__regid__] + +class MultiLinesRsetSelectorTC(CubicWebTC): + def setUp(self): + super(MultiLinesRsetSelectorTC, self).setUp() + self.req = self.request() + self.req.execute('INSERT CWGroup G: G name "group1"') + self.req.execute('INSERT CWGroup G: G name "group2"') + self.commit() + self.rset = self.req.execute('Any G WHERE G is CWGroup') + + def test_default_op_in_selector(self): + expected = len(self.rset) + selector = multi_lines_rset(expected) + self.assertEqual(selector(None, self.req, self.rset), 1) + self.assertEqual(selector(None, self.req, None), 0) + selector = multi_lines_rset(expected + 1) + self.assertEqual(selector(None, self.req, self.rset), 0) + self.assertEqual(selector(None, self.req, None), 0) + selector = multi_lines_rset(expected - 1) + self.assertEqual(selector(None, self.req, self.rset), 0) + self.assertEqual(selector(None, self.req, None), 0) + + def test_without_rset(self): + expected = len(self.rset) + selector = multi_lines_rset(expected) + self.assertEqual(selector(None, self.req, None), 0) + selector = multi_lines_rset(expected + 1) + self.assertEqual(selector(None, self.req, None), 0) + selector = multi_lines_rset(expected - 1) + self.assertEqual(selector(None, self.req, None), 0) + + def test_with_operators(self): + expected = len(self.rset) + + # Format 'expected', 'operator', 'assert' + testdata = (( expected, eq, 1), + ( expected+1, eq, 0), + ( expected-1, eq, 0), + ( expected, le, 1), + ( expected+1, le, 1), + ( expected-1, le, 0), + ( expected-1, gt, 1), + ( expected, gt, 0), + ( expected+1, gt, 0), + ( expected+1, lt, 1), + ( expected, lt, 0), + ( expected-1, lt, 0)) + + for (expected, operator, assertion) in testdata: + selector = multi_lines_rset(expected, operator) + yield self.assertEqual, selector(None, self.req, self.rset), assertion + + if __name__ == '__main__': unittest_main()