selectors.py
changeset 6395 30582ba8b368
parent 6389 72ba82a26e05
child 6397 66401ba9332a
equal deleted inserted replaced
6394:eb9a5bd778bc 6395:30582ba8b368
   476             return score - 0.5
   476             return score - 0.5
   477         if score == 1:
   477         if score == 1:
   478             return score + 0.5
   478             return score + 0.5
   479         return score
   479         return score
   480 
   480 
       
   481 
       
   482 class configuration_values(Selector):
       
   483     """Return 1 if the instance has an option set to a given value(s) in its
       
   484     configuration file.
       
   485     """
       
   486     # XXX this selector could be evaluated on startup
       
   487     def __init__(self, key, values):
       
   488         self._key = key
       
   489         if isinstance(values, basestring):
       
   490             values = (values,)
       
   491         self._values = frozenset(values)
       
   492 
       
   493     @lltrace
       
   494     def __call__(self, cls, req, **kwargs):
       
   495         try:
       
   496             return self._score
       
   497         except AttributeError:
       
   498             self._score = req.vreg.config[self._key] in self._values
       
   499         return self._score
       
   500 
   481 # rset selectors ##############################################################
   501 # rset selectors ##############################################################
   482 
   502 
   483 @objectify_selector
   503 @objectify_selector
   484 @lltrace
   504 @lltrace
   485 def none_rset(cls, req, rset=None, **kwargs):
   505 def none_rset(cls, req, rset=None, **kwargs):
   531 
   551 
   532 
   552 
   533 class multi_lines_rset(Selector):
   553 class multi_lines_rset(Selector):
   534     """Return 1 if the operator expression matches between `num` elements
   554     """Return 1 if the operator expression matches between `num` elements
   535     in the result set and the `expected` value if defined.
   555     in the result set and the `expected` value if defined.
   536     
   556 
   537     By default, multi_lines_rset(expected) matches equality expression:
   557     By default, multi_lines_rset(expected) matches equality expression:
   538         `nb` row(s) in result set equals to expected value
   558         `nb` row(s) in result set equals to expected value
   539     But, you can perform richer comparisons by overriding default operator:
   559     But, you can perform richer comparisons by overriding default operator:
   540         multi_lines_rset(expected, operator.gt)
   560         multi_lines_rset(expected, operator.gt)
   541     
   561 
   542     If `expected` is None, return 1 if the result set contains *at least*
   562     If `expected` is None, return 1 if the result set contains *at least*
   543     two rows.
   563     two rows.
   544     If rset is None, return 0.
   564     If rset is None, return 0.
   545     """
   565     """
   546     def __init__(self, expected=None, operator=eq):
   566     def __init__(self, expected=None, operator=eq):
   799             if isinstance(score, (int, long)):
   819             if isinstance(score, (int, long)):
   800                 return score
   820                 return score
   801             return 1
   821             return 1
   802         self.score_entity = intscore
   822         self.score_entity = intscore
   803 
   823 
   804 class attribute_edited(EntitySelector):
       
   805     """Scores if the specified attribute has been edited
       
   806     This is useful for selection of forms by the edit controller.
       
   807     The initial use case is on a form, in conjunction with match_transition,
       
   808     which will not score at edit time::
       
   809 
       
   810      is_instance('Version') & (match_transition('ready') |
       
   811                                attribute_edited('publication_date'))
       
   812     """
       
   813     def __init__(self, attribute, once_is_enough=False):
       
   814         super(attribute_edited, self).__init__(once_is_enough)
       
   815         self._attribute = attribute
       
   816 
       
   817     def score_entity(self, entity):
       
   818         return eid_param(role_name(self._attribute, 'subject'), entity.eid) in entity._cw.form
       
   819 
   824 
   820 class has_mimetype(EntitySelector):
   825 class has_mimetype(EntitySelector):
   821     """Return 1 if the entity adapt to IDownloadable and has the given MIME type.
   826     """Return 1 if the entity adapt to IDownloadable and has the given MIME type.
   822 
   827 
   823     You can give 'image/' to match any image for instance, or 'image/png' to match
   828     You can give 'image/' to match any image for instance, or 'image/png' to match
  1146             return len(req.execute(self.rql, {'x': rset[row][col],
  1151             return len(req.execute(self.rql, {'x': rset[row][col],
  1147                                               'u': req.user.eid}))
  1152                                               'u': req.user.eid}))
  1148         except Unauthorized:
  1153         except Unauthorized:
  1149             return 0
  1154             return 0
  1150 
  1155 
       
  1156 
       
  1157 class is_in_state(score_entity):
       
  1158     """return 1 if entity is in one of the states given as argument list
       
  1159 
       
  1160     you should use this instead of your own :class:`score_entity` selector to
       
  1161     avoid some gotchas:
       
  1162 
       
  1163     * possible views gives a fake entity with no state
       
  1164     * you must use the latest tr info, not entity.in_state for repository side
       
  1165       checking of the current state
       
  1166     """
       
  1167     def __init__(self, *states):
       
  1168         def score(entity, states=set(states)):
       
  1169             trinfo = entity.cw_adapt_to('IWorkflowable').latest_trinfo()
       
  1170             try:
       
  1171                 return trinfo.new_state.name in states
       
  1172             except AttributeError:
       
  1173                 return None
       
  1174         super(is_in_state, self).__init__(score)
       
  1175 
       
  1176 
  1151 # logged user selectors ########################################################
  1177 # logged user selectors ########################################################
  1152 
  1178 
  1153 @objectify_selector
  1179 @objectify_selector
  1154 @lltrace
  1180 @lltrace
  1155 def no_cnx(cls, req, **kwargs):
  1181 def no_cnx(cls, req, **kwargs):
  1208                     return 0
  1234                     return 0
  1209                 score = 1
  1235                 score = 1
  1210             else:
  1236             else:
  1211                 score = all(user.owns(r[col]) for r in rset)
  1237                 score = all(user.owns(r[col]) for r in rset)
  1212         return score
  1238         return score
  1213 
       
  1214 
       
  1215 class configuration_values(Selector):
       
  1216     """Return 1 if the instance is configured according to
       
  1217     the given value(s)"""
       
  1218 
       
  1219     def __init__(self, key, values):
       
  1220         self._key = key
       
  1221         if isinstance(values, basestring):
       
  1222             values = (values,)
       
  1223         self._values = frozenset(values)
       
  1224 
       
  1225     @lltrace
       
  1226     def __call__(self, cls, req, **kwargs):
       
  1227         try:
       
  1228             return self._score
       
  1229         except AttributeError:
       
  1230             self._score = req.vreg.config[self._key] in self._values
       
  1231         return self._score
       
  1232 
  1239 
  1233 # Web request selectors ########################################################
  1240 # Web request selectors ########################################################
  1234 
  1241 
  1235 # XXX deprecate
  1242 # XXX deprecate
  1236 @objectify_selector
  1243 @objectify_selector
  1382             if eschema.has_local_role('add') or eschema.has_perm(req, 'add'):
  1389             if eschema.has_local_role('add') or eschema.has_perm(req, 'add'):
  1383                 return score
  1390                 return score
  1384         return 0
  1391         return 0
  1385 
  1392 
  1386 
  1393 
       
  1394 class attribute_edited(EntitySelector):
       
  1395     """Scores if the specified attribute has been edited This is useful for
       
  1396     selection of forms by the edit controller.
       
  1397 
       
  1398     The initial use case is on a form, in conjunction with match_transition,
       
  1399     which will not score at edit time::
       
  1400 
       
  1401      is_instance('Version') & (match_transition('ready') |
       
  1402                                attribute_edited('publication_date'))
       
  1403     """
       
  1404     def __init__(self, attribute, once_is_enough=False):
       
  1405         super(attribute_edited, self).__init__(once_is_enough)
       
  1406         self._attribute = attribute
       
  1407 
       
  1408     def score_entity(self, entity):
       
  1409         return eid_param(role_name(self._attribute, 'subject'), entity.eid) in entity._cw.form
       
  1410 
       
  1411 
  1387 # Other selectors ##############################################################
  1412 # Other selectors ##############################################################
  1388 
  1413 
  1389 
  1414 
  1390 class match_transition(ExpectedValueSelector):
  1415 class match_transition(ExpectedValueSelector):
  1391     """Return 1 if `transition` argument is found in the input context
  1416     """Return 1 if `transition` argument is found in the input context which has
  1392       which has a `.name` attribute matching one of the expected names
  1417     a `.name` attribute matching one of the expected names given to the
  1393       given to the initializer
  1418     initializer.
  1394     """
  1419     """
  1395     @lltrace
  1420     @lltrace
  1396     def __call__(self, cls, req, transition=None, **kwargs):
  1421     def __call__(self, cls, req, transition=None, **kwargs):
  1397         # XXX check this is a transition that apply to the object?
  1422         # XXX check this is a transition that apply to the object?
  1398         if transition is not None and getattr(transition, 'name', None) in self.expected:
  1423         if transition is not None and getattr(transition, 'name', None) in self.expected:
  1399             return 1
  1424             return 1
  1400         return 0
  1425         return 0
  1401 
  1426 
  1402 class is_in_state(score_entity):
       
  1403     """return 1 if entity is in one of the states given as argument list
       
  1404 
       
  1405     you should use this instead of your own :class:`score_entity` selector to
       
  1406     avoid some gotchas:
       
  1407 
       
  1408     * possible views gives a fake entity with no state
       
  1409     * you must use the latest tr info, not entity.in_state for repository side
       
  1410       checking of the current state
       
  1411     """
       
  1412     def __init__(self, *states):
       
  1413         def score(entity, states=set(states)):
       
  1414             trinfo = entity.cw_adapt_to('IWorkflowable').latest_trinfo()
       
  1415             try:
       
  1416                 return trinfo.new_state.name in states
       
  1417             except AttributeError:
       
  1418                 return None
       
  1419         super(is_in_state, self).__init__(score)
       
  1420 
  1427 
  1421 @objectify_selector
  1428 @objectify_selector
  1422 def debug_mode(cls, req, rset=None, **kwargs):
  1429 def debug_mode(cls, req, rset=None, **kwargs):
  1423     """Return 1 if running in debug mode"""
  1430     """Return 1 if running in debug mode."""
  1424     return req.vreg.config.debugmode and 1 or 0
  1431     return req.vreg.config.debugmode and 1 or 0
  1425 
  1432 
  1426 ## deprecated stuff ############################################################
  1433 ## deprecated stuff ############################################################
  1427 
  1434 
  1428 entity_implements = class_renamed('entity_implements', is_instance)
  1435 entity_implements = class_renamed('entity_implements', is_instance)