common/selectors.py
branchtls-sprint
changeset 633 087e3f1e87c8
parent 631 99f5852f8604
child 634 0badd061ce0f
equal deleted inserted replaced
632:3a394a90b702 633:087e3f1e87c8
    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)
   488                 return 1
   512                 return 1
   489         return 0
   513         return 0
   490 
   514 
   491 
   515 
   492 class may_add_relation(EntitySelector):
   516 class may_add_relation(EntitySelector):
   493     """initializer a relation type and optional role (default to 'subject') as
   517     """initializer takes a relation type and optional role (default to
   494     argument
   518     'subject') as argument
   495 
   519 
   496     if row is specified check the relation may be added to the entity at the
   520     if row is specified check the relation may be added to the entity at the
   497     given row/col (if row specified) or to every entities in the given col (if
   521     given row/col (if row specified) or to every entities in the given col (if
   498     row is not specified)
   522     row is not specified)
   499     """
   523     """
   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,
   751 
   778 
   752 searchstate_accept_one_but_etype = chainall(searchstate_accept_one, but_etype,
   779 searchstate_accept_one_but_etype = chainall(searchstate_accept_one, but_etype,
   753                                             name='searchstate_accept_one_but_etype')
   780                                             name='searchstate_accept_one_but_etype')
   754 searchstate_accept_one_but_etype_selector = deprecated_function(
   781 searchstate_accept_one_but_etype_selector = deprecated_function(
   755     searchstate_accept_one_but_etype)
   782     searchstate_accept_one_but_etype)
       
   783 
       
   784 #req_form_params_selector = deprecated_function(match_form_params) # form_params
       
   785 #kwargs_selector = deprecated_function(match_kwargs) # expected_kwargs