selectors.py
changeset 6366 1806148d6ce8
parent 6141 b8287e54b528
parent 6364 ad9ed9803eb6
child 6389 72ba82a26e05
equal deleted inserted replaced
6333:e3994fcc21c3 6366:1806148d6ce8
   192 
   192 
   193 __docformat__ = "restructuredtext en"
   193 __docformat__ = "restructuredtext en"
   194 
   194 
   195 import logging
   195 import logging
   196 from warnings import warn
   196 from warnings import warn
       
   197 from operator import eq
   197 
   198 
   198 from logilab.common.deprecation import class_renamed
   199 from logilab.common.deprecation import class_renamed
   199 from logilab.common.compat import all, any
   200 from logilab.common.compat import all, any
   200 from logilab.common.interface import implements as implements_iface
   201 from logilab.common.interface import implements as implements_iface
   201 
   202 
   528         return 1
   529         return 1
   529     return 0
   530     return 0
   530 
   531 
   531 
   532 
   532 class multi_lines_rset(Selector):
   533 class multi_lines_rset(Selector):
   533     """If `nb` is specified, return 1 if the result set has exactly `nb` row of
   534     """Return 1 if the operator expression matches between `num` elements
   534     result. Else (`nb` is None), return 1 if the result set contains *at least*
   535     in the result set and the `expected` value if defined.
       
   536     
       
   537     By default, multi_lines_rset(expected) matches equality expression:
       
   538         `nb` row(s) in result set equals to expected value
       
   539     But, you can perform richer comparisons by overriding default operator:
       
   540         multi_lines_rset(expected, operator.gt)
       
   541     
       
   542     If `expected` is None, return 1 if the result set contains *at least*
   535     two rows.
   543     two rows.
   536     """
   544     If rset is None, return 0.
   537     def __init__(self, nb=None):
   545     """
   538         self.expected = nb
   546     def __init__(self, expected=None, operator=eq):
       
   547         self.expected = expected
       
   548         self.operator = operator
   539 
   549 
   540     def match_expected(self, num):
   550     def match_expected(self, num):
   541         if self.expected is None:
   551         if self.expected is None:
   542             return num > 1
   552             return num > 1
   543         return num == self.expected
   553         return self.operator(num, self.expected)
   544 
   554 
   545     @lltrace
   555     @lltrace
   546     def __call__(self, cls, req, rset=None, **kwargs):
   556     def __call__(self, cls, req, rset=None, **kwargs):
   547         return int(rset is not None and self.match_expected(rset.rowcount))
   557         return int(rset is not None and self.match_expected(rset.rowcount))
   548 
   558 
  1037     def __call__(self, cls, req, rset=None, row=None, col=0, **kwargs):
  1047     def __call__(self, cls, req, rset=None, row=None, col=0, **kwargs):
  1038         if kwargs.get('entity'):
  1048         if kwargs.get('entity'):
  1039             return self.score_entity(kwargs['entity'])
  1049             return self.score_entity(kwargs['entity'])
  1040         if rset is None:
  1050         if rset is None:
  1041             return 0
  1051             return 0
  1042         user = req.user
       
  1043         action = self.action
       
  1044         if row is None:
  1052         if row is None:
  1045             score = 0
  1053             score = 0
  1046             need_local_check = []
  1054             need_local_check = []
  1047             geteschema = req.vreg.schema.eschema
  1055             geteschema = req.vreg.schema.eschema
       
  1056             user = req.user
       
  1057             action = self.action
  1048             for etype in rset.column_types(0):
  1058             for etype in rset.column_types(0):
  1049                 if etype in BASE_TYPES:
  1059                 if etype in BASE_TYPES:
  1050                     return 0
  1060                     return 0
  1051                 eschema = geteschema(etype)
  1061                 eschema = geteschema(etype)
  1052                 if not user.matching_groups(eschema.get_groups(action)):
  1062                 if not user.matching_groups(eschema.get_groups(action)):
  1059                         return 0
  1069                         return 0
  1060                 score += 1
  1070                 score += 1
  1061             if need_local_check:
  1071             if need_local_check:
  1062                 # check local role for entities of necessary types
  1072                 # check local role for entities of necessary types
  1063                 for i, row in enumerate(rset):
  1073                 for i, row in enumerate(rset):
  1064                     if not rset.description[i][0] in need_local_check:
  1074                     if not rset.description[i][col] in need_local_check:
  1065                         continue
  1075                         continue
  1066                     if not self.score(req, rset, i, col):
  1076                     # micro-optimisation instead of calling self.score(req,
       
  1077                     # rset, i, col): rset may be large
       
  1078                     if not rset.get_entity(i, col).cw_has_perm(action):
  1067                         return 0
  1079                         return 0
  1068                 score += 1
  1080                 score += 1
  1069             return score
  1081             return score
  1070         return self.score(req, rset, row, col)
  1082         return self.score(req, rset, row, col)
  1071 
  1083