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