68 else: |
68 else: |
69 selname = selector.__name__ |
69 selname = selector.__name__ |
70 oid = cls.id |
70 oid = cls.id |
71 ret = selector(cls, *args, **kwargs) |
71 ret = selector(cls, *args, **kwargs) |
72 if TRACED_OIDS == 'all' or oid in TRACED_OIDS: |
72 if TRACED_OIDS == 'all' or oid in TRACED_OIDS: |
73 SELECTOR_LOGGER.warning('selector %s returned %s for %s', selname, ret, cls) |
73 #SELECTOR_LOGGER.warning('selector %s returned %s for %s', selname, ret, cls) |
|
74 print 'selector %s returned %s for %s' % (selname, ret, cls) |
74 return ret |
75 return ret |
75 traced.__name__ = selector.__name__ |
76 traced.__name__ = selector.__name__ |
76 return traced |
77 return traced |
77 |
78 |
78 class traced_selection(object): |
79 class traced_selection(object): |
211 return 0 |
212 return 0 |
212 multitype_selector = deprecated_function(two_etypes_rset) |
213 multitype_selector = deprecated_function(two_etypes_rset) |
213 |
214 |
214 |
215 |
215 class match_search_state(Selector): |
216 class match_search_state(Selector): |
216 def __init__(self, *expected_states): |
217 def __init__(self, *expected): |
217 self.expected_states = expected_states |
218 self.expected = expected |
218 |
219 |
|
220 @lltrace |
219 def __call__(self, cls, req, rset, row=None, col=0, **kwargs): |
221 def __call__(self, cls, req, rset, row=None, col=0, **kwargs): |
220 """checks if the current request search state is in one of the expected states |
222 """checks if the current request search state is in one of the expected states |
221 the wrapped class |
223 the wrapped class |
222 |
224 |
223 search state should be either 'normal' or 'linksearch' (eg searching for an |
225 search state should be either 'normal' or 'linksearch' (eg searching for an |
224 object to create a relation with another) |
226 object to create a relation with another) |
225 """ |
227 """ |
226 try: |
228 try: |
227 if not req.search_state[0] in cls.search_states: |
229 if not req.search_state[0] in self.expected: |
228 return 0 |
230 return 0 |
229 except AttributeError: |
231 except AttributeError: |
230 return 1 # class doesn't care about search state, accept it |
232 return 1 # class doesn't care about search state, accept it |
231 return 1 |
233 return 1 |
|
234 |
|
235 |
|
236 class match_form_params(match_search_state): |
|
237 """check if parameters specified as initializer arguments are specified |
|
238 in request form parameters |
|
239 """ |
|
240 @lltrace |
|
241 def __call__(self, cls, req, *args, **kwargs): |
|
242 score = 0 |
|
243 for param in self.expected: |
|
244 val = req.form.get(param) |
|
245 if not val: |
|
246 return 0 |
|
247 score += 1 |
|
248 return len(self.expected) |
|
249 |
|
250 |
|
251 class match_kwargs(match_search_state): |
|
252 """check if parameters specified as initializer arguments are specified |
|
253 in named parameters |
|
254 """ |
|
255 @lltrace |
|
256 def __call__(self, cls, req, *args, **kwargs): |
|
257 for arg in self.expected: |
|
258 if not arg in kwargs: |
|
259 return 0 |
|
260 return len(self.expected) |
|
261 |
232 |
262 |
233 @lltrace |
263 @lltrace |
234 def anonymous_user(cls, req, *args, **kwargs): |
264 def anonymous_user(cls, req, *args, **kwargs): |
235 """accept if user is anonymous""" |
265 """accept if user is anonymous""" |
236 if req.cnx.anonymous_connection: |
266 if req.cnx.anonymous_connection: |
241 @lltrace |
271 @lltrace |
242 def authenticated_user(cls, req, *args, **kwargs): |
272 def authenticated_user(cls, req, *args, **kwargs): |
243 """accept if user is authenticated""" |
273 """accept if user is authenticated""" |
244 return not anonymous_user(cls, req, *args, **kwargs) |
274 return not anonymous_user(cls, req, *args, **kwargs) |
245 not_anonymous_selector = deprecated_function(authenticated_user) |
275 not_anonymous_selector = deprecated_function(authenticated_user) |
246 |
|
247 @lltrace |
|
248 def match_form_params(cls, req, *args, **kwargs): |
|
249 """check if parameters specified by the form_params attribute on |
|
250 the wrapped class are specified in request form parameters |
|
251 """ |
|
252 score = 0 |
|
253 for param in cls.form_params: |
|
254 val = req.form.get(param) |
|
255 if not val: |
|
256 return 0 |
|
257 score += 1 |
|
258 return score + 1 |
|
259 req_form_params_selector = deprecated_function(match_form_params) |
|
260 |
|
261 @lltrace |
|
262 def match_kwargs(cls, req, *args, **kwargs): |
|
263 """check if arguments specified by the expected_kwargs attribute on |
|
264 the wrapped class are specified in given named parameters |
|
265 """ |
|
266 values = [] |
|
267 for arg in cls.expected_kwargs: |
|
268 if not arg in kwargs: |
|
269 return 0 |
|
270 return 1 |
|
271 kwargs_selector = deprecated_function(match_kwargs) |
|
272 |
276 |
273 # abstract selectors ########################################################## |
277 # abstract selectors ########################################################## |
274 |
278 |
275 class EClassSelector(Selector): |
279 class EClassSelector(Selector): |
276 """abstract class for selectors working on the entity classes of the result |
280 """abstract class for selectors working on the entity classes of the result |
362 # entity type |
366 # entity type |
363 iface = eclass.vreg.etype_class(iface) |
367 iface = eclass.vreg.etype_class(iface) |
364 if implements_iface(eclass, iface): |
368 if implements_iface(eclass, iface): |
365 score += 1 |
369 score += 1 |
366 if getattr(iface, '__registry__', None) == 'etypes': |
370 if getattr(iface, '__registry__', None) == 'etypes': |
|
371 score += 1 |
367 # adjust score if the interface is an entity class |
372 # adjust score if the interface is an entity class |
368 if iface is eclass: |
373 if iface is eclass: |
369 score += len(eclass.e_schema.ancestors()) + 1 |
374 score += len(eclass.e_schema.ancestors()) |
|
375 print 'is majoration', len(eclass.e_schema.ancestors()) |
370 else: |
376 else: |
371 parents = [e.type for e in eclass.e_schema.ancestors()] |
377 parents = [e.type for e in eclass.e_schema.ancestors()] |
372 for index, etype in enumerate(reversed(parents)): |
378 for index, etype in enumerate(reversed(parents)): |
373 basecls = eclass.vreg.etype_class(etype) |
379 basecls = eclass.vreg.etype_class(etype) |
374 if iface is basecls: |
380 if iface is basecls: |
375 score += index + 1 |
381 score += index |
|
382 print 'etype majoration', index |
376 break |
383 break |
377 return score |
384 return score |
|
385 |
|
386 |
|
387 class specified_etype_implements(implements): |
|
388 """return the "interface score" for class associated to 'etype' (expected in |
|
389 request form or arguments) |
|
390 """ |
|
391 |
|
392 @lltrace |
|
393 def __call__(cls, req, *args, **kwargs): |
|
394 try: |
|
395 etype = req.form['etype'] |
|
396 except KeyError: |
|
397 try: |
|
398 etype = kwargs['etype'] |
|
399 except KeyError: |
|
400 return 0 |
|
401 return self.score_class(cls.vreg.etype_class(etype), req) |
378 |
402 |
379 |
403 |
380 class relation_possible(EClassSelector): |
404 class relation_possible(EClassSelector): |
381 """initializer takes relation name as argument and an optional role (default |
405 """initializer takes relation name as argument and an optional role (default |
382 as subject) and target type (default to unspecified) |
406 as subject) and target type (default to unspecified) |
563 return 1 |
587 return 1 |
564 return 0 |
588 return 0 |
565 |
589 |
566 |
590 |
567 class has_add_permission(EClassSelector): |
591 class has_add_permission(EClassSelector): |
568 |
592 """return 1 if the user may add some entity of the types found in the |
|
593 result set (0 else) |
|
594 """ |
569 def score_class(self, eclass, req): |
595 def score_class(self, eclass, req): |
570 eschema = eclass.e_schema |
596 eschema = eclass.e_schema |
571 if not (eschema.is_final() or eschema.is_subobject(strict=True)) \ |
597 if not (eschema.is_final() or eschema.is_subobject(strict=True)) \ |
572 and eschema.has_perm(req, 'add'): |
598 and eschema.has_perm(req, 'add'): |
573 return 1 |
599 return 1 |
574 return 0 |
600 return 0 |
575 |
601 |
576 |
602 |
577 class score_entity(EntitySelector): |
603 class score_entity(EntitySelector): |
|
604 """initializer takes a function as argument (which is expected to take an |
|
605 entity as argument) |
|
606 |
|
607 return the score returned by the function on the entity at the given row/col |
|
608 (if row specified) or the sum of the score for every entities in the given |
|
609 col (if row is not specified). Return 0 at the first entity scoring to zero. |
|
610 """ |
578 def __init__(self, scorefunc): |
611 def __init__(self, scorefunc): |
579 self.score_entity = scorefunc |
612 self.score_entity = scorefunc |
580 |
613 |
|
614 |
581 # XXX not so basic selectors ###################################################### |
615 # XXX not so basic selectors ###################################################### |
582 |
|
583 @lltrace |
|
584 def accept_etype(cls, req, *args, **kwargs): |
|
585 """check etype presence in request form *and* accepts conformance""" |
|
586 try: |
|
587 etype = req.form['etype'] |
|
588 except KeyError: |
|
589 try: |
|
590 etype = kwargs['etype'] |
|
591 except KeyError: |
|
592 return 0 |
|
593 return implements(*cls.accepts).score_class(cls.vreg.etype_class(etype), req) |
|
594 etype_form_selector = deprecated_function(accept_etype) |
|
595 |
616 |
596 @lltrace |
617 @lltrace |
597 def _rql_condition(cls, req, rset, row=None, col=0, **kwargs): |
618 def _rql_condition(cls, req, rset, row=None, col=0, **kwargs): |
598 """accept single entity result set if the entity match an rql condition |
619 """accept single entity result set if the entity match an rql condition |
599 """ |
620 """ |
695 |
716 |
696 def implement_interface(cls, req, rset, row=None, col=0, **kwargs): |
717 def implement_interface(cls, req, rset, row=None, col=0, **kwargs): |
697 return implements(*cls.accepts_interfaces)(cls, req, rset, row, col) |
718 return implements(*cls.accepts_interfaces)(cls, req, rset, row, col) |
698 _interface_selector = deprecated_function(implement_interface) |
719 _interface_selector = deprecated_function(implement_interface) |
699 interface_selector = deprecated_function(implement_interface) |
720 interface_selector = deprecated_function(implement_interface) |
700 implement_interface = deprecated_function(implement_interface) |
721 implement_interface = deprecated_function(implement_interface, 'use implements') |
|
722 |
|
723 def accept_etype(cls, req, *args, **kwargs): |
|
724 """check etype presence in request form *and* accepts conformance""" |
|
725 return specified_etype_implements(*cls.accepts)(cls, req, *args) |
|
726 etype_form_selector = deprecated_function(accept_etype) |
|
727 accept_etype = deprecated_function(accept_etype, 'use specified_etype_implements') |
701 |
728 |
702 def searchstate_selector(cls, req, rset, row=None, col=0, **kwargs): |
729 def searchstate_selector(cls, req, rset, row=None, col=0, **kwargs): |
703 return match_search_state(cls.search_states)(cls, req, rset, row, col) |
730 return match_search_state(cls.search_states)(cls, req, rset, row, col) |
704 searchstate_selector = deprecated_function(searchstate_selector) |
731 searchstate_selector = deprecated_function(searchstate_selector) |
705 |
732 |
706 def match_user_group(cls, req, rset=None, row=None, col=0, **kwargs): |
733 def match_user_group(cls, req, rset=None, row=None, col=0, **kwargs): |
707 return match_user_groups(cls.require_groups)(cls, req, rset, row, col, **kwargs) |
734 return match_user_groups(*cls.require_groups)(cls, req, rset, row, col, **kwargs) |
708 in_group_selector = deprecated_function(match_user_group) |
735 in_group_selector = deprecated_function(match_user_group) |
709 match_user_group = deprecated_function(match_user_group) |
736 match_user_group = deprecated_function(match_user_group) |
710 |
737 |
711 def has_relation(cls, req, rset, row=None, col=0, **kwargs): |
738 def has_relation(cls, req, rset, row=None, col=0, **kwargs): |
712 return relation_possible(cls.rtype, role(cls), cls.etype, |
739 return relation_possible(cls.rtype, role(cls), cls.etype, |