vregistry.py
author Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
Wed, 18 Feb 2009 20:23:43 +0100
branchtls-sprint
changeset 827 3f08481e6e51
parent 804 cc339d3ff7ae
child 835 7dcb11dd443e
permissions -rw-r--r--
provide negation operator for selectors, unfortunately, it's not possible to user the python keyword 'not'
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     1
"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     2
* the vregistry handle various type of objects interacting
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     3
  together. The vregistry handle registration of dynamically loaded
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     4
  objects and provide a convenient api access to those objects
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     5
  according to a context
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     6
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     7
* to interact with the vregistry, object should inherit from the
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     8
  VObject abstract class
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     9
  
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    10
* the registration procedure is delegated to a registerer. Each
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    11
  registerable vobject must defines its registerer class using the
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    12
  __registerer__ attribute.  A registerer is instantianted at
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    13
  registration time after what the instance is lost
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    14
  
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    15
* the selection procedure has been generalized by delegating to a
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    16
  selector, which is responsible to score the vobject according to the
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    17
  current state (req, rset, row, col). At the end of the selection, if
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    18
  a vobject class has been found, an instance of this class is
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    19
  returned. The selector is instantiated at vobject registration
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    20
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    21
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    22
:organization: Logilab
615
38bc11ac845b don't use chainall when it's not necessary
sylvain.thenault@logilab.fr
parents: 355
diff changeset
    23
:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    24
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    25
"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    26
__docformat__ = "restructuredtext en"
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    27
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    28
import sys
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    29
from os import listdir, stat
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    30
from os.path import dirname, join, realpath, split, isdir
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    31
from logging import getLogger
712
ce49e3885453 remove autoselectors metaclass, __select__ is built during registration
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 711
diff changeset
    32
import types
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    33
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    34
from cubicweb import CW_SOFTWARE_ROOT, set_log_methods
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    35
from cubicweb import RegistryNotFound, ObjectNotFound, NoSelectableObject
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    36
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    37
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    38
754
937f5feac7f0 kill vobject_helpver
sylvain.thenault@logilab.fr
parents: 741
diff changeset
    39
class registerer(object):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    40
    """do whatever is needed at registration time for the wrapped
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    41
    class, according to current application schema and already
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    42
    registered objects of the same kind (i.e. same registry name and
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    43
    same id).
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    44
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    45
    The wrapped class may be skipped, some previously selected object
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    46
    may be kicked out... After whatever works needed, if the object or
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    47
    a transformed object is returned, it will be added to previously
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    48
    registered objects.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    49
    """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    50
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    51
    def __init__(self, registry, vobject):
754
937f5feac7f0 kill vobject_helpver
sylvain.thenault@logilab.fr
parents: 741
diff changeset
    52
        self.registry = registry
937f5feac7f0 kill vobject_helpver
sylvain.thenault@logilab.fr
parents: 741
diff changeset
    53
        self.vobject = vobject
937f5feac7f0 kill vobject_helpver
sylvain.thenault@logilab.fr
parents: 741
diff changeset
    54
        self.config = registry.config
937f5feac7f0 kill vobject_helpver
sylvain.thenault@logilab.fr
parents: 741
diff changeset
    55
        self.schema = registry.schema
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    56
        self.kicked = set()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    57
    
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    58
    def do_it_yourself(self, registered):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    59
        raise NotImplementedError(str(self.vobject))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    60
        
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    61
    def kick(self, registered, kicked):
355
89ad20af9e4c oops, these were committed unintentionnally
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 354
diff changeset
    62
        self.debug('kicking vobject %s', kicked)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    63
        registered.remove(kicked)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    64
        self.kicked.add(kicked.classid())
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    65
        
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    66
    def skip(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    67
        self.debug('no schema compat, skipping %s', self.vobject)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    68
718
f7011679437a doc update, move yes_registerer here
sylvain.thenault@logilab.fr
parents: 714
diff changeset
    69
class yes_registerer(registerer):
f7011679437a doc update, move yes_registerer here
sylvain.thenault@logilab.fr
parents: 714
diff changeset
    70
    """register without any other action"""
f7011679437a doc update, move yes_registerer here
sylvain.thenault@logilab.fr
parents: 714
diff changeset
    71
    def do_it_yourself(self, registered):
f7011679437a doc update, move yes_registerer here
sylvain.thenault@logilab.fr
parents: 714
diff changeset
    72
        return self.vobject
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    73
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    74
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    75
class VObject(object):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    76
    """visual object, use to be handled somehow by the visual components
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    77
    registry.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    78
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    79
    The following attributes should be set on concret vobject subclasses:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    80
    
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    81
    :__registry__:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    82
      name of the registry for this object (string like 'views',
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    83
      'templates'...)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    84
    :id:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    85
      object's identifier in the registry (string like 'main',
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    86
      'primary', 'folder_box')
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    87
    :__select__:
719
2a610efe21ce default to yes_registerer
sylvain.thenault@logilab.fr
parents: 718
diff changeset
    88
      class'selector
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    89
      
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    90
    Moreover, the `__abstract__` attribute may be set to True to indicate
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    91
    that a vobject is abstract and should not be registered
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    92
    """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    93
    # necessary attributes to interact with the registry
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    94
    id = None
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    95
    __registry__ = None
719
2a610efe21ce default to yes_registerer
sylvain.thenault@logilab.fr
parents: 718
diff changeset
    96
    __registerer__ = yes_registerer
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    97
    __select__ = None
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    98
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    99
    @classmethod
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   100
    def registered(cls, registry):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   101
        """called by the registry when the vobject has been registered.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   102
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   103
        It must return the  object that will be actually registered (this
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   104
        may be the right hook to create an instance for example). By
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   105
        default the vobject is returned without any transformation.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   106
        """
741
8c810ee593a3 fix selectors compat
sylvain.thenault@logilab.fr
parents: 739
diff changeset
   107
        cls.build___select__()
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   108
        return cls
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   109
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   110
    @classmethod
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   111
    def selected(cls, *args, **kwargs):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   112
        """called by the registry when the vobject has been selected.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   113
        
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   114
        It must return the  object that will be actually returned by the
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   115
        .select method (this may be the right hook to create an
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   116
        instance for example). By default the selected object is
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   117
        returned without any transformation.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   118
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   119
        return cls
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   120
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   121
    @classmethod
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   122
    def classid(cls):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   123
        """returns a unique identifier for the vobject"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   124
        return '%s.%s' % (cls.__module__, cls.__name__)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   125
736
18c940e3f98d need safety belt for class registered twice (during test for instance)
sylvain.thenault@logilab.fr
parents: 735
diff changeset
   126
    # XXX bw compat code
712
ce49e3885453 remove autoselectors metaclass, __select__ is built during registration
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 711
diff changeset
   127
    @classmethod
ce49e3885453 remove autoselectors metaclass, __select__ is built during registration
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 711
diff changeset
   128
    def build___select__(cls):
ce49e3885453 remove autoselectors metaclass, __select__ is built during registration
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 711
diff changeset
   129
        classdict = cls.__dict__
736
18c940e3f98d need safety belt for class registered twice (during test for instance)
sylvain.thenault@logilab.fr
parents: 735
diff changeset
   130
        if ('__select__' in classdict and '__selectors__' in classdict
18c940e3f98d need safety belt for class registered twice (during test for instance)
sylvain.thenault@logilab.fr
parents: 735
diff changeset
   131
            and not '__selgenerated__' in classdict):
18c940e3f98d need safety belt for class registered twice (during test for instance)
sylvain.thenault@logilab.fr
parents: 735
diff changeset
   132
            raise TypeError("__select__ and __selectors__ can't be used together on class %s" % cls)
712
ce49e3885453 remove autoselectors metaclass, __select__ is built during registration
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 711
diff changeset
   133
        if '__selectors__' in classdict:
736
18c940e3f98d need safety belt for class registered twice (during test for instance)
sylvain.thenault@logilab.fr
parents: 735
diff changeset
   134
            cls.__selgenerated__ = True
712
ce49e3885453 remove autoselectors metaclass, __select__ is built during registration
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 711
diff changeset
   135
            # case where __selectors__ is defined locally (but __select__
ce49e3885453 remove autoselectors metaclass, __select__ is built during registration
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 711
diff changeset
   136
            # is in a parent class)
ce49e3885453 remove autoselectors metaclass, __select__ is built during registration
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 711
diff changeset
   137
            selectors = classdict['__selectors__']
ce49e3885453 remove autoselectors metaclass, __select__ is built during registration
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 711
diff changeset
   138
            if len(selectors) == 1:
ce49e3885453 remove autoselectors metaclass, __select__ is built during registration
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 711
diff changeset
   139
                # micro optimization: don't bother with AndSelector if there's
ce49e3885453 remove autoselectors metaclass, __select__ is built during registration
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 711
diff changeset
   140
                # only one selector
741
8c810ee593a3 fix selectors compat
sylvain.thenault@logilab.fr
parents: 739
diff changeset
   141
                select = _instantiate_selector(selectors[0])
8c810ee593a3 fix selectors compat
sylvain.thenault@logilab.fr
parents: 739
diff changeset
   142
            else:
780
5b6c93816871 fix selector search and refactor auto-instantiation
sylvain.thenault@logilab.fr
parents: 760
diff changeset
   143
                select = AndSelector(*selectors)
741
8c810ee593a3 fix selectors compat
sylvain.thenault@logilab.fr
parents: 739
diff changeset
   144
            cls.__select__ = select
712
ce49e3885453 remove autoselectors metaclass, __select__ is built during registration
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 711
diff changeset
   145
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   146
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   147
class VRegistry(object):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   148
    """class responsible to register, propose and select the various
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   149
    elements used to build the web interface. Currently, we have templates,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   150
    views, actions and components.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   151
    """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   152
    
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   153
    def __init__(self, config):#, cache_size=1000):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   154
        self.config = config
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   155
        # dictionnary of registry (themself dictionnary) by name
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   156
        self._registries = {}
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   157
        self._lastmodifs = {}
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   158
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   159
    def reset(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   160
        self._registries = {}
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   161
        self._lastmodifs = {}
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   162
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   163
    def __getitem__(self, key):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   164
        return self._registries[key]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   165
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   166
    def get(self, key, default=None):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   167
        return self._registries.get(key, default)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   168
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   169
    def items(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   170
        return self._registries.items()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   171
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   172
    def values(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   173
        return self._registries.values()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   174
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   175
    def __contains__(self, key):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   176
        return key in self._registries
660
5233a9457f6b work in progress, draft for manual registration
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 652
diff changeset
   177
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   178
    def registry(self, name):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   179
        """return the registry (dictionary of class objects) associated to
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   180
        this name
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   181
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   182
        try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   183
            return self._registries[name]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   184
        except KeyError:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   185
            raise RegistryNotFound(name), None, sys.exc_info()[-1]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   186
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   187
    def registry_objects(self, name, oid=None):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   188
        """returns objects registered with the given oid in the given registry.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   189
        If no oid is given, return all objects in this registry
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   190
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   191
        registry = self.registry(name)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   192
        if oid:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   193
            try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   194
                return registry[oid]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   195
            except KeyError:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   196
                raise ObjectNotFound(oid), None, sys.exc_info()[-1]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   197
        else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   198
            result = []
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   199
            for objs in registry.values():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   200
                result += objs
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   201
            return result
665
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   202
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   203
    def object_by_id(self, registry, cid, *args, **kwargs):
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   204
        """return the most specific component according to the resultset"""
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   205
        objects = self[registry][cid]
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   206
        assert len(objects) == 1, objects
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   207
        return objects[0].selected(*args, **kwargs)
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   208
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   209
    # methods for explicit (un)registration ###################################
668
61b2328f9ed9 rename registration callback, clear argument to register
sylvain.thenault@logilab.fr
parents: 665
diff changeset
   210
61b2328f9ed9 rename registration callback, clear argument to register
sylvain.thenault@logilab.fr
parents: 665
diff changeset
   211
#     def clear(self, key):
61b2328f9ed9 rename registration callback, clear argument to register
sylvain.thenault@logilab.fr
parents: 665
diff changeset
   212
#         regname, oid = key.split('.')
61b2328f9ed9 rename registration callback, clear argument to register
sylvain.thenault@logilab.fr
parents: 665
diff changeset
   213
#         self[regname].pop(oid, None)
695
356da23c57f1 try a register_all method
sylvain.thenault@logilab.fr
parents: 693
diff changeset
   214
    def register_all(self, objects, modname, butclasses=()):
356da23c57f1 try a register_all method
sylvain.thenault@logilab.fr
parents: 693
diff changeset
   215
        for obj in objects:
356da23c57f1 try a register_all method
sylvain.thenault@logilab.fr
parents: 693
diff changeset
   216
            try:
356da23c57f1 try a register_all method
sylvain.thenault@logilab.fr
parents: 693
diff changeset
   217
                if obj.__module__ != modname or obj in butclasses:
356da23c57f1 try a register_all method
sylvain.thenault@logilab.fr
parents: 693
diff changeset
   218
                    continue
356da23c57f1 try a register_all method
sylvain.thenault@logilab.fr
parents: 693
diff changeset
   219
                oid = obj.id
356da23c57f1 try a register_all method
sylvain.thenault@logilab.fr
parents: 693
diff changeset
   220
            except AttributeError:
356da23c57f1 try a register_all method
sylvain.thenault@logilab.fr
parents: 693
diff changeset
   221
                continue
356da23c57f1 try a register_all method
sylvain.thenault@logilab.fr
parents: 693
diff changeset
   222
            if oid:
356da23c57f1 try a register_all method
sylvain.thenault@logilab.fr
parents: 693
diff changeset
   223
                self.register(obj)
356da23c57f1 try a register_all method
sylvain.thenault@logilab.fr
parents: 693
diff changeset
   224
                
668
61b2328f9ed9 rename registration callback, clear argument to register
sylvain.thenault@logilab.fr
parents: 665
diff changeset
   225
    def register(self, obj, registryname=None, oid=None, clear=False):
665
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   226
        """base method to add an object in the registry"""
707
21a59b468f1a __selectors__ -> __select__
sylvain.thenault@logilab.fr
parents: 698
diff changeset
   227
        assert not '__abstract__' in obj.__dict__
665
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   228
        registryname = registryname or obj.__registry__
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   229
        oid = oid or obj.id
739
39721e56b56d assert oid
sylvain.thenault@logilab.fr
parents: 736
diff changeset
   230
        assert oid
665
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   231
        registry = self._registries.setdefault(registryname, {})
668
61b2328f9ed9 rename registration callback, clear argument to register
sylvain.thenault@logilab.fr
parents: 665
diff changeset
   232
        if clear:
61b2328f9ed9 rename registration callback, clear argument to register
sylvain.thenault@logilab.fr
parents: 665
diff changeset
   233
            vobjects = registry[oid] =  []
61b2328f9ed9 rename registration callback, clear argument to register
sylvain.thenault@logilab.fr
parents: 665
diff changeset
   234
        else:
61b2328f9ed9 rename registration callback, clear argument to register
sylvain.thenault@logilab.fr
parents: 665
diff changeset
   235
            vobjects = registry.setdefault(oid, [])
665
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   236
        # registered() is technically a classmethod but is not declared
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   237
        # as such because we need to compose registered in some cases
682
sylvain.thenault@logilab.fr
parents: 673
diff changeset
   238
        vobject = obj.registered.im_func(obj, self)
665
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   239
        assert not vobject in vobjects
804
cc339d3ff7ae assert __select__ is callable
sylvain.thenault@logilab.fr
parents: 780
diff changeset
   240
        assert callable(vobject.__select__), vobject
665
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   241
        vobjects.append(vobject)
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   242
        try:
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   243
            vname = vobject.__name__
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   244
        except AttributeError:
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   245
            vname = vobject.__class__.__name__
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   246
        self.debug('registered vobject %s in registry %s with id %s',
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   247
                   vname, registryname, oid)
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   248
        # automatic reloading management
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   249
        self._registered['%s.%s' % (obj.__module__, oid)] = obj
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   250
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   251
    def unregister(self, obj, registryname=None):
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   252
        registryname = registryname or obj.__registry__
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   253
        registry = self.registry(registryname)
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   254
        removed_id = obj.classid()
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   255
        for registered in registry[obj.id]:
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   256
            # use classid() to compare classes because vreg will probably
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   257
            # have its own version of the class, loaded through execfile
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   258
            if registered.classid() == removed_id:
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   259
                # XXX automatic reloading management
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   260
                try:
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   261
                    registry[obj.id].remove(registered)
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   262
                except ValueError:
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   263
                    self.warning('can\'t remove %s, no id %s in the %s registry',
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   264
                                 removed_id, obj.id, registryname)
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   265
                except ValueError:
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   266
                    self.warning('can\'t remove %s, not in the %s registry with id %s',
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   267
                                 removed_id, registryname, obj.id)
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   268
#                 else:
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   269
#                     # if objects is empty, remove oid from registry
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   270
#                     if not registry[obj.id]:
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   271
#                         del regcontent[oid]                    
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   272
                break
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   273
    
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   274
    def register_and_replace(self, obj, replaced, registryname=None):
673
64c50cb17d70 factorized impl
sylvain.thenault@logilab.fr
parents: 668
diff changeset
   275
        if hasattr(replaced, 'classid'):
64c50cb17d70 factorized impl
sylvain.thenault@logilab.fr
parents: 668
diff changeset
   276
            replaced = replaced.classid()
665
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   277
        registryname = registryname or obj.__registry__
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   278
        registry = self.registry(registryname)
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   279
        registered_objs = registry[obj.id]
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   280
        for index, registered in enumerate(registered_objs):
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   281
            if registered.classid() == replaced:
673
64c50cb17d70 factorized impl
sylvain.thenault@logilab.fr
parents: 668
diff changeset
   282
                del registry[obj.id][index]
64c50cb17d70 factorized impl
sylvain.thenault@logilab.fr
parents: 668
diff changeset
   283
                break
64c50cb17d70 factorized impl
sylvain.thenault@logilab.fr
parents: 668
diff changeset
   284
        self.register(obj, registryname=registryname)
665
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   285
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   286
    # dynamic selection methods ###############################################
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   287
    
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   288
    def select(self, vobjects, *args, **kwargs):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   289
        """return an instance of the most specific object according
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   290
        to parameters
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   291
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   292
        raise NoSelectableObject if not object apply
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   293
        """
177
73aa03734425 check we don't get selection ambiguity: if yes, log error in production env, raise in other modes
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 0
diff changeset
   294
        score, winners = 0, []
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   295
        for vobject in vobjects:
735
d22baa02cbaa __select__ is not a classmethod anymore, it's a pure function (or a Selector instance),
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 734
diff changeset
   296
            vobjectscore = vobject.__select__(vobject, *args, **kwargs)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   297
            if vobjectscore > score:
177
73aa03734425 check we don't get selection ambiguity: if yes, log error in production env, raise in other modes
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 0
diff changeset
   298
                score, winners = vobjectscore, [vobject]
73aa03734425 check we don't get selection ambiguity: if yes, log error in production env, raise in other modes
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 0
diff changeset
   299
            elif vobjectscore > 0 and vobjectscore == score:
73aa03734425 check we don't get selection ambiguity: if yes, log error in production env, raise in other modes
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 0
diff changeset
   300
                winners.append(vobject)
73aa03734425 check we don't get selection ambiguity: if yes, log error in production env, raise in other modes
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 0
diff changeset
   301
        if not winners:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   302
            raise NoSelectableObject('args: %s\nkwargs: %s %s'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   303
                                     % (args, kwargs.keys(), [repr(v) for v in vobjects]))
177
73aa03734425 check we don't get selection ambiguity: if yes, log error in production env, raise in other modes
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 0
diff changeset
   304
        if len(winners) > 1:
73aa03734425 check we don't get selection ambiguity: if yes, log error in production env, raise in other modes
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 0
diff changeset
   305
            if self.config.mode == 'installed':
73aa03734425 check we don't get selection ambiguity: if yes, log error in production env, raise in other modes
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 0
diff changeset
   306
                self.error('select ambiguity, args: %s\nkwargs: %s %s',
73aa03734425 check we don't get selection ambiguity: if yes, log error in production env, raise in other modes
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 0
diff changeset
   307
                           args, kwargs.keys(), [repr(v) for v in winners])
73aa03734425 check we don't get selection ambiguity: if yes, log error in production env, raise in other modes
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 0
diff changeset
   308
            else:
73aa03734425 check we don't get selection ambiguity: if yes, log error in production env, raise in other modes
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 0
diff changeset
   309
                raise Exception('select ambiguity, args: %s\nkwargs: %s %s'
73aa03734425 check we don't get selection ambiguity: if yes, log error in production env, raise in other modes
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 0
diff changeset
   310
                                % (args, kwargs.keys(), [repr(v) for v in winners]))
73aa03734425 check we don't get selection ambiguity: if yes, log error in production env, raise in other modes
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 0
diff changeset
   311
        winner = winners[0]
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   312
        # return the result of the .selected method of the vobject
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   313
        return winner.selected(*args, **kwargs)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   314
    
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   315
    def possible_objects(self, registry, *args, **kwargs):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   316
        """return an iterator on possible objects in a registry for this result set
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   317
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   318
        actions returned are classes, not instances
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   319
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   320
        for vobjects in self.registry(registry).values():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   321
            try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   322
                yield self.select(vobjects, *args, **kwargs)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   323
            except NoSelectableObject:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   324
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   325
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   326
    def select_object(self, registry, cid, *args, **kwargs):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   327
        """return the most specific component according to the resultset"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   328
        return self.select(self.registry_objects(registry, cid), *args, **kwargs)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   329
    
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   330
    # intialization methods ###################################################
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   331
    
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   332
    def register_objects(self, path, force_reload=None):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   333
        if force_reload is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   334
            force_reload = self.config.mode == 'dev'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   335
        elif not force_reload:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   336
            # force_reload == False usually mean modules have been reloaded
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   337
            # by another connection, so we want to update the registry
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   338
            # content even if there has been no module content modification
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   339
            self.reset()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   340
        # need to clean sys.path this to avoid import confusion pb (i.e.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   341
        # having the same module loaded as 'cubicweb.web.views' subpackage and
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   342
        # as views'  or 'web.views' subpackage
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   343
        # this is mainly for testing purpose, we should'nt need this in
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   344
        # production environment
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   345
        for webdir in (join(dirname(realpath(__file__)), 'web'),
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   346
                       join(dirname(__file__), 'web')):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   347
            if webdir in sys.path:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   348
                sys.path.remove(webdir)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   349
        if CW_SOFTWARE_ROOT in sys.path:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   350
            sys.path.remove(CW_SOFTWARE_ROOT)        
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   351
        # load views from each directory in the application's path
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   352
        change = False
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   353
        for fileordirectory in path:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   354
            if isdir(fileordirectory):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   355
                if self.read_directory(fileordirectory, force_reload):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   356
                    change = True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   357
            else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   358
                directory, filename = split(fileordirectory)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   359
                if self.load_file(directory, filename, force_reload):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   360
                    change = True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   361
        if change:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   362
            for registry, objects in self.items():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   363
                self.debug('available in registry %s: %s', registry,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   364
                           sorted(objects))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   365
        return change
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   366
    
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   367
    def read_directory(self, directory, force_reload=False):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   368
        """read a directory and register available views"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   369
        modified_on = stat(realpath(directory))[-2]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   370
        # only read directory if it was modified
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   371
        _lastmodifs = self._lastmodifs
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   372
        if directory in _lastmodifs and modified_on <= _lastmodifs[directory]:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   373
            return False
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   374
        self.info('loading directory %s', directory)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   375
        for filename in listdir(directory):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   376
            if filename[-3:] == '.py':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   377
                try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   378
                    self.load_file(directory, filename, force_reload)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   379
                except OSError:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   380
                    # this typically happens on emacs backup files (.#foo.py)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   381
                    self.warning('Unable to load file %s. It is likely to be a backup file',
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   382
                                 filename)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   383
                except Exception, ex:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   384
                    if self.config.mode in ('dev', 'test'):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   385
                        raise
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   386
                    self.exception('%r while loading file %s', ex, filename)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   387
        _lastmodifs[directory] = modified_on
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   388
        return True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   389
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   390
    def load_file(self, directory, filename, force_reload=False):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   391
        """load visual objects from a python file"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   392
        from logilab.common.modutils import load_module_from_modpath, modpath_from_file
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   393
        filepath = join(directory, filename)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   394
        modified_on = stat(filepath)[-2]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   395
        modpath = modpath_from_file(join(directory, filename))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   396
        modname = '.'.join(modpath)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   397
        unregistered = {}
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   398
        _lastmodifs = self._lastmodifs
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   399
        if filepath in _lastmodifs:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   400
            # only load file if it was modified
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   401
            if modified_on <= _lastmodifs[filepath]:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   402
                return
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   403
            else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   404
                # if it was modified, unregister all exisiting objects
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   405
                # from this module, and keep track of what was unregistered
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   406
                unregistered = self.unregister_module_vobjects(modname)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   407
        # load the module
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   408
        module = load_module_from_modpath(modpath, use_sys=not force_reload)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   409
        registered = self.load_module(module)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   410
        # if something was unregistered, we need to update places where it was
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   411
        # referenced 
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   412
        if unregistered:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   413
            # oldnew_mapping = {}
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   414
            oldnew_mapping = dict((unregistered[name], registered[name])
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   415
                                  for name in unregistered if name in registered)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   416
            self.update_registered_subclasses(oldnew_mapping)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   417
        _lastmodifs[filepath] = modified_on
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   418
        return True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   419
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   420
    def load_module(self, module):
665
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   421
        self._registered = {}
668
61b2328f9ed9 rename registration callback, clear argument to register
sylvain.thenault@logilab.fr
parents: 665
diff changeset
   422
        if hasattr(module, 'registration_callback'):
61b2328f9ed9 rename registration callback, clear argument to register
sylvain.thenault@logilab.fr
parents: 665
diff changeset
   423
            module.registration_callback(self)
660
5233a9457f6b work in progress, draft for manual registration
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 652
diff changeset
   424
        else:
5233a9457f6b work in progress, draft for manual registration
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 652
diff changeset
   425
            self.info('loading %s', module)
5233a9457f6b work in progress, draft for manual registration
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 652
diff changeset
   426
            for objname, obj in vars(module).items():
5233a9457f6b work in progress, draft for manual registration
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 652
diff changeset
   427
                if objname.startswith('_'):
5233a9457f6b work in progress, draft for manual registration
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 652
diff changeset
   428
                    continue
665
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   429
                self.load_ancestors_then_object(module.__name__, obj)
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   430
        return self._registered
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   431
    
665
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   432
    def load_ancestors_then_object(self, modname, obj):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   433
        # skip imported classes
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   434
        if getattr(obj, '__module__', None) != modname:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   435
            return
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   436
        # skip non registerable object
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   437
        try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   438
            if not issubclass(obj, VObject):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   439
                return
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   440
        except TypeError:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   441
            return
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   442
        objname = '%s.%s' % (modname, obj.__name__)
665
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   443
        if objname in self._registered:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   444
            return
665
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   445
        self._registered[objname] = obj
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   446
        for parent in obj.__bases__:
665
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   447
            self.load_ancestors_then_object(modname, parent)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   448
        self.load_object(obj)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   449
            
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   450
    def load_object(self, obj):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   451
        try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   452
            self.register_vobject_class(obj)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   453
        except Exception, ex:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   454
            if self.config.mode in ('test', 'dev'):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   455
                raise
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   456
            self.exception('vobject %s registration failed: %s', obj, ex)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   457
        
665
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   458
    # old automatic registration XXX deprecated ###############################
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   459
    
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   460
    def register_vobject_class(self, cls):
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   461
        """handle vobject class registration
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   462
        
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   463
        vobject class with __abstract__ == True in their local dictionnary or
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   464
        with a name starting starting by an underscore are not registered.
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   465
        Also a vobject class needs to have __registry__ and id attributes set
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   466
        to a non empty string to be registered.
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   467
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   468
        Registration is actually handled by vobject's registerer.
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   469
        """
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   470
        if (cls.__dict__.get('__abstract__') or cls.__name__[0] == '_'
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   471
            or not cls.__registry__ or not cls.id):
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   472
            return
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   473
        regname = cls.__registry__
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   474
        if cls.id in self.config['disable-%s' % regname]:
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   475
            return
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   476
        registry = self._registries.setdefault(regname, {})
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   477
        vobjects = registry.setdefault(cls.id, [])
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   478
        registerer = cls.__registerer__(self, cls)
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   479
        cls = registerer.do_it_yourself(vobjects)
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   480
        if cls:
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   481
            self.register(cls)
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   482
            
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   483
    def unregister_module_vobjects(self, modname):
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   484
        """removes registered objects coming from a given module
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   485
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   486
        returns a dictionnary classid/class of all classes that will need
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   487
        to be updated after reload (i.e. vobjects referencing classes defined
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   488
        in the <modname> module)
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   489
        """
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   490
        unregistered = {}
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   491
        # browse each registered object
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   492
        for registry, objdict in self.items():
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   493
            for oid, objects in objdict.items():
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   494
                for obj in objects[:]:
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   495
                    objname = obj.classid()
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   496
                    # if the vobject is defined in this module, remove it
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   497
                    if objname.startswith(modname):
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   498
                        unregistered[objname] = obj
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   499
                        objects.remove(obj)
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   500
                        self.debug('unregistering %s in %s registry',
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   501
                                  objname, registry)
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   502
                    # if not, check if the vobject can be found in baseclasses
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   503
                    # (because we also want subclasses to be updated)
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   504
                    else:
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   505
                        if not isinstance(obj, type):
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   506
                            obj = obj.__class__
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   507
                        for baseclass in obj.__bases__:
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   508
                            if hasattr(baseclass, 'classid'):
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   509
                                baseclassid = baseclass.classid()
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   510
                                if baseclassid.startswith(modname):
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   511
                                    unregistered[baseclassid] = baseclass
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   512
                # update oid entry
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   513
                if objects:
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   514
                    objdict[oid] = objects
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   515
                else:
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   516
                    del objdict[oid]
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   517
        return unregistered
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   518
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   519
    def update_registered_subclasses(self, oldnew_mapping):
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   520
        """updates subclasses of re-registered vobjects
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   521
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   522
        if baseviews.PrimaryView is changed, baseviews.py will be reloaded
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   523
        automatically and the new version of PrimaryView will be registered.
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   524
        But all existing subclasses must also be notified of this change, and
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   525
        that's what this method does
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   526
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   527
        :param oldnew_mapping: a dict mapping old version of a class to
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   528
                               the new version
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   529
        """
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   530
        # browse each registered object
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   531
        for objdict in self.values():
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   532
            for objects in objdict.values():
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   533
                for obj in objects:
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   534
                    if not isinstance(obj, type):
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   535
                        obj = obj.__class__
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   536
                    # build new baseclasses tuple
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   537
                    newbases = tuple(oldnew_mapping.get(baseclass, baseclass)
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   538
                                     for baseclass in obj.__bases__)
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   539
                    # update obj's baseclasses tuple (__bases__) if needed
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   540
                    if newbases != obj.__bases__:
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   541
                        self.debug('updating %s.%s base classes',
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   542
                                  obj.__module__, obj.__name__)
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   543
                        obj.__bases__ = newbases
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   544
        
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   545
# init logging 
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   546
set_log_methods(VObject, getLogger('cubicweb'))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   547
set_log_methods(VRegistry, getLogger('cubicweb.registry'))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   548
set_log_methods(registerer, getLogger('cubicweb.registration'))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   549
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   550
630
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   551
# selector base classes and operations ########################################
631
99f5852f8604 major selector refactoring (mostly to avoid looking for select parameters on the target class), start accept / interface unification)
sylvain.thenault@logilab.fr
parents: 630
diff changeset
   552
630
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   553
class Selector(object):
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   554
    """base class for selector classes providing implementation
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   555
    for operators ``&`` and ``|``
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   556
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   557
    This class is only here to give access to binary operators, the
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   558
    selector logic itself should be implemented in the __call__ method
718
f7011679437a doc update, move yes_registerer here
sylvain.thenault@logilab.fr
parents: 714
diff changeset
   559
f7011679437a doc update, move yes_registerer here
sylvain.thenault@logilab.fr
parents: 714
diff changeset
   560
f7011679437a doc update, move yes_registerer here
sylvain.thenault@logilab.fr
parents: 714
diff changeset
   561
    a selector is called to help choosing the correct object for a
f7011679437a doc update, move yes_registerer here
sylvain.thenault@logilab.fr
parents: 714
diff changeset
   562
    particular context by returning a score (`int`) telling how well
f7011679437a doc update, move yes_registerer here
sylvain.thenault@logilab.fr
parents: 714
diff changeset
   563
    the class given as first argument apply to the given context.
f7011679437a doc update, move yes_registerer here
sylvain.thenault@logilab.fr
parents: 714
diff changeset
   564
f7011679437a doc update, move yes_registerer here
sylvain.thenault@logilab.fr
parents: 714
diff changeset
   565
    0 score means that the class doesn't apply.
630
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   566
    """
698
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   567
711
f758b86cf484 Selector objects need to provide a `func_name` attribute for minimum (backward)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 710
diff changeset
   568
    @property
f758b86cf484 Selector objects need to provide a `func_name` attribute for minimum (backward)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 710
diff changeset
   569
    def func_name(self):
f758b86cf484 Selector objects need to provide a `func_name` attribute for minimum (backward)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 710
diff changeset
   570
        # backward compatibility
f758b86cf484 Selector objects need to provide a `func_name` attribute for minimum (backward)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 710
diff changeset
   571
        return self.__class__.__name__
f758b86cf484 Selector objects need to provide a `func_name` attribute for minimum (backward)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 710
diff changeset
   572
698
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   573
    def search_selector(self, selector):
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   574
        """search for the given selector or selector instance in the selectors
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   575
        tree. Return it of None if not found
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   576
        """
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   577
        if self is selector:
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   578
            return self
721
sylvain.thenault@logilab.fr
parents: 719
diff changeset
   579
        if isinstance(selector, type) and isinstance(self, selector):
698
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   580
            return self
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   581
        return None
780
5b6c93816871 fix selector search and refactor auto-instantiation
sylvain.thenault@logilab.fr
parents: 760
diff changeset
   582
5b6c93816871 fix selector search and refactor auto-instantiation
sylvain.thenault@logilab.fr
parents: 760
diff changeset
   583
    def __str__(self):
5b6c93816871 fix selector search and refactor auto-instantiation
sylvain.thenault@logilab.fr
parents: 760
diff changeset
   584
        return self.__class__.__name__
698
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   585
    
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   586
    def __and__(self, other):
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   587
        return AndSelector(self, other)
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   588
    def __rand__(self, other):
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   589
        return AndSelector(other, self)
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   590
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   591
    def __or__(self, other):
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   592
        return OrSelector(self, other)
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   593
    def __ror__(self, other):
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   594
        return OrSelector(other, self)
827
3f08481e6e51 provide negation operator for selectors, unfortunately, it's not possible to user the python keyword 'not'
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 804
diff changeset
   595
3f08481e6e51 provide negation operator for selectors, unfortunately, it's not possible to user the python keyword 'not'
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 804
diff changeset
   596
    def __invert__(self):
3f08481e6e51 provide negation operator for selectors, unfortunately, it's not possible to user the python keyword 'not'
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 804
diff changeset
   597
        return NotSelector(self)
698
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   598
    
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   599
    # XXX (function | function) or (function & function) not managed yet
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   600
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   601
    def __call__(self, cls, *args, **kwargs):
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   602
        return NotImplementedError("selector %s must implement its logic "
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   603
                                   "in its __call__ method" % self.__class__)
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   604
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   605
class MultiSelector(Selector):
718
f7011679437a doc update, move yes_registerer here
sylvain.thenault@logilab.fr
parents: 714
diff changeset
   606
    """base class for compound selector classes"""
f7011679437a doc update, move yes_registerer here
sylvain.thenault@logilab.fr
parents: 714
diff changeset
   607
    
630
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   608
    def __init__(self, *selectors):
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   609
        self.selectors = self.merge_selectors(selectors)
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   610
780
5b6c93816871 fix selector search and refactor auto-instantiation
sylvain.thenault@logilab.fr
parents: 760
diff changeset
   611
    def __str__(self):
5b6c93816871 fix selector search and refactor auto-instantiation
sylvain.thenault@logilab.fr
parents: 760
diff changeset
   612
        return '%s(%s)' % (self.__class__.__name__,
5b6c93816871 fix selector search and refactor auto-instantiation
sylvain.thenault@logilab.fr
parents: 760
diff changeset
   613
                           ','.join(str(s) for s in self.selectors))
5b6c93816871 fix selector search and refactor auto-instantiation
sylvain.thenault@logilab.fr
parents: 760
diff changeset
   614
630
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   615
    @classmethod
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   616
    def merge_selectors(cls, selectors):
780
5b6c93816871 fix selector search and refactor auto-instantiation
sylvain.thenault@logilab.fr
parents: 760
diff changeset
   617
        """deal with selector instanciation when necessary and merge
5b6c93816871 fix selector search and refactor auto-instantiation
sylvain.thenault@logilab.fr
parents: 760
diff changeset
   618
        multi-selectors if possible:
630
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   619
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   620
        AndSelector(AndSelector(sel1, sel2), AndSelector(sel3, sel4))
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   621
        ==> AndSelector(sel1, sel2, sel3, sel4)
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   622
        """
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   623
        merged_selectors = []
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   624
        for selector in selectors:
780
5b6c93816871 fix selector search and refactor auto-instantiation
sylvain.thenault@logilab.fr
parents: 760
diff changeset
   625
            selector = _instantiate_selector(selector)
5b6c93816871 fix selector search and refactor auto-instantiation
sylvain.thenault@logilab.fr
parents: 760
diff changeset
   626
            assert isinstance(selector, Selector), selector
630
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   627
            if isinstance(selector, cls):
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   628
                merged_selectors += selector.selectors
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   629
            else:
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   630
                merged_selectors.append(selector)
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   631
        return merged_selectors
693
cf0817dfc787 reimplements chainall/chainfirst using [And/Or], implemenent search_selector function on Selector base class
sylvain.thenault@logilab.fr
parents: 686
diff changeset
   632
cf0817dfc787 reimplements chainall/chainfirst using [And/Or], implemenent search_selector function on Selector base class
sylvain.thenault@logilab.fr
parents: 686
diff changeset
   633
    def search_selector(self, selector):
cf0817dfc787 reimplements chainall/chainfirst using [And/Or], implemenent search_selector function on Selector base class
sylvain.thenault@logilab.fr
parents: 686
diff changeset
   634
        """search for the given selector or selector instance in the selectors
cf0817dfc787 reimplements chainall/chainfirst using [And/Or], implemenent search_selector function on Selector base class
sylvain.thenault@logilab.fr
parents: 686
diff changeset
   635
        tree. Return it of None if not found
cf0817dfc787 reimplements chainall/chainfirst using [And/Or], implemenent search_selector function on Selector base class
sylvain.thenault@logilab.fr
parents: 686
diff changeset
   636
        """
cf0817dfc787 reimplements chainall/chainfirst using [And/Or], implemenent search_selector function on Selector base class
sylvain.thenault@logilab.fr
parents: 686
diff changeset
   637
        for childselector in self.selectors:
780
5b6c93816871 fix selector search and refactor auto-instantiation
sylvain.thenault@logilab.fr
parents: 760
diff changeset
   638
            if childselector is selector:
5b6c93816871 fix selector search and refactor auto-instantiation
sylvain.thenault@logilab.fr
parents: 760
diff changeset
   639
                return childselector
5b6c93816871 fix selector search and refactor auto-instantiation
sylvain.thenault@logilab.fr
parents: 760
diff changeset
   640
            found = childselector.search_selector(selector)
5b6c93816871 fix selector search and refactor auto-instantiation
sylvain.thenault@logilab.fr
parents: 760
diff changeset
   641
            if found is not None:
5b6c93816871 fix selector search and refactor auto-instantiation
sylvain.thenault@logilab.fr
parents: 760
diff changeset
   642
                return found
693
cf0817dfc787 reimplements chainall/chainfirst using [And/Or], implemenent search_selector function on Selector base class
sylvain.thenault@logilab.fr
parents: 686
diff changeset
   643
        return None
630
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   644
697
06807984e610 provide objectify_selector decorator for very simple selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 695
diff changeset
   645
    
06807984e610 provide objectify_selector decorator for very simple selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 695
diff changeset
   646
def objectify_selector(selector_func):
06807984e610 provide objectify_selector decorator for very simple selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 695
diff changeset
   647
    """convenience decorator for simple selectors where a class definition
06807984e610 provide objectify_selector decorator for very simple selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 695
diff changeset
   648
    would be overkill::
06807984e610 provide objectify_selector decorator for very simple selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 695
diff changeset
   649
06807984e610 provide objectify_selector decorator for very simple selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 695
diff changeset
   650
        @objectify_selector
06807984e610 provide objectify_selector decorator for very simple selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 695
diff changeset
   651
        def yes(cls, *args, **kwargs):
06807984e610 provide objectify_selector decorator for very simple selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 695
diff changeset
   652
            return 1
06807984e610 provide objectify_selector decorator for very simple selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 695
diff changeset
   653
        
06807984e610 provide objectify_selector decorator for very simple selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 695
diff changeset
   654
    """
06807984e610 provide objectify_selector decorator for very simple selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 695
diff changeset
   655
    return type(selector_func.__name__, (Selector,),
734
4153a82a60a4 get kwargs as well
sylvain.thenault@logilab.fr
parents: 727
diff changeset
   656
                {'__call__': lambda self, *args, **kwargs: selector_func(*args, **kwargs)})
697
06807984e610 provide objectify_selector decorator for very simple selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 695
diff changeset
   657
712
ce49e3885453 remove autoselectors metaclass, __select__ is built during registration
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 711
diff changeset
   658
def _instantiate_selector(selector):
ce49e3885453 remove autoselectors metaclass, __select__ is built during registration
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 711
diff changeset
   659
    """ensures `selector` is a `Selector` instance
ce49e3885453 remove autoselectors metaclass, __select__ is built during registration
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 711
diff changeset
   660
    
ce49e3885453 remove autoselectors metaclass, __select__ is built during registration
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 711
diff changeset
   661
    NOTE: This should only be used locally in build___select__()
ce49e3885453 remove autoselectors metaclass, __select__ is built during registration
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 711
diff changeset
   662
    """
ce49e3885453 remove autoselectors metaclass, __select__ is built during registration
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 711
diff changeset
   663
    if isinstance(selector, types.FunctionType):
ce49e3885453 remove autoselectors metaclass, __select__ is built during registration
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 711
diff changeset
   664
        return objectify_selector(selector)()
727
30fe8f5afbd8 fix _instantiate_selector() mini bug (make sure obj is a class before calling issubclass)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 724
diff changeset
   665
    if isinstance(selector, type) and issubclass(selector, Selector):
712
ce49e3885453 remove autoselectors metaclass, __select__ is built during registration
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 711
diff changeset
   666
        return selector()
ce49e3885453 remove autoselectors metaclass, __select__ is built during registration
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 711
diff changeset
   667
    return selector
ce49e3885453 remove autoselectors metaclass, __select__ is built during registration
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 711
diff changeset
   668
630
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   669
698
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   670
class AndSelector(MultiSelector):
630
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   671
    """and-chained selectors (formerly known as chainall)"""
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   672
    def __call__(self, cls, *args, **kwargs):
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   673
        score = 0
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   674
        for selector in self.selectors:
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   675
            partscore = selector(cls, *args, **kwargs)
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   676
            if not partscore:
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   677
                return 0
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   678
            score += partscore
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   679
        return score
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   680
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   681
698
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   682
class OrSelector(MultiSelector):
630
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   683
    """or-chained selectors (formerly known as chainfirst)"""
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   684
    def __call__(self, cls, *args, **kwargs):
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   685
        for selector in self.selectors:
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   686
            partscore = selector(cls, *args, **kwargs)
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   687
            if partscore:
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   688
                return partscore
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   689
        return 0
693
cf0817dfc787 reimplements chainall/chainfirst using [And/Or], implemenent search_selector function on Selector base class
sylvain.thenault@logilab.fr
parents: 686
diff changeset
   690
827
3f08481e6e51 provide negation operator for selectors, unfortunately, it's not possible to user the python keyword 'not'
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 804
diff changeset
   691
class NotSelector(Selector):
3f08481e6e51 provide negation operator for selectors, unfortunately, it's not possible to user the python keyword 'not'
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 804
diff changeset
   692
    """negation selector"""
3f08481e6e51 provide negation operator for selectors, unfortunately, it's not possible to user the python keyword 'not'
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 804
diff changeset
   693
    def __init__(self, selector):
3f08481e6e51 provide negation operator for selectors, unfortunately, it's not possible to user the python keyword 'not'
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 804
diff changeset
   694
        self.selector = selector
3f08481e6e51 provide negation operator for selectors, unfortunately, it's not possible to user the python keyword 'not'
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 804
diff changeset
   695
3f08481e6e51 provide negation operator for selectors, unfortunately, it's not possible to user the python keyword 'not'
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 804
diff changeset
   696
    def __call__(self, cls, *args, **kwargs):
3f08481e6e51 provide negation operator for selectors, unfortunately, it's not possible to user the python keyword 'not'
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 804
diff changeset
   697
        score = self.selector(cls, *args, **kwargs)
3f08481e6e51 provide negation operator for selectors, unfortunately, it's not possible to user the python keyword 'not'
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 804
diff changeset
   698
        return not score
3f08481e6e51 provide negation operator for selectors, unfortunately, it's not possible to user the python keyword 'not'
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 804
diff changeset
   699
3f08481e6e51 provide negation operator for selectors, unfortunately, it's not possible to user the python keyword 'not'
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 804
diff changeset
   700
    def __str__(self):
3f08481e6e51 provide negation operator for selectors, unfortunately, it's not possible to user the python keyword 'not'
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 804
diff changeset
   701
        return 'NOT(%s)' % super(NotSelector, self).__str__()
693
cf0817dfc787 reimplements chainall/chainfirst using [And/Or], implemenent search_selector function on Selector base class
sylvain.thenault@logilab.fr
parents: 686
diff changeset
   702
cf0817dfc787 reimplements chainall/chainfirst using [And/Or], implemenent search_selector function on Selector base class
sylvain.thenault@logilab.fr
parents: 686
diff changeset
   703
# advanced selector building functions ########################################
cf0817dfc787 reimplements chainall/chainfirst using [And/Or], implemenent search_selector function on Selector base class
sylvain.thenault@logilab.fr
parents: 686
diff changeset
   704
cf0817dfc787 reimplements chainall/chainfirst using [And/Or], implemenent search_selector function on Selector base class
sylvain.thenault@logilab.fr
parents: 686
diff changeset
   705
def chainall(*selectors, **kwargs):
cf0817dfc787 reimplements chainall/chainfirst using [And/Or], implemenent search_selector function on Selector base class
sylvain.thenault@logilab.fr
parents: 686
diff changeset
   706
    """return a selector chaining given selectors. If one of
cf0817dfc787 reimplements chainall/chainfirst using [And/Or], implemenent search_selector function on Selector base class
sylvain.thenault@logilab.fr
parents: 686
diff changeset
   707
    the selectors fail, selection will fail, else the returned score
cf0817dfc787 reimplements chainall/chainfirst using [And/Or], implemenent search_selector function on Selector base class
sylvain.thenault@logilab.fr
parents: 686
diff changeset
   708
    will be the sum of each selector'score
cf0817dfc787 reimplements chainall/chainfirst using [And/Or], implemenent search_selector function on Selector base class
sylvain.thenault@logilab.fr
parents: 686
diff changeset
   709
    """
cf0817dfc787 reimplements chainall/chainfirst using [And/Or], implemenent search_selector function on Selector base class
sylvain.thenault@logilab.fr
parents: 686
diff changeset
   710
    assert selectors
759
e044f28372bd chainall / chainfirst ensures selectors are instantiated
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 741
diff changeset
   711
    # XXX do we need to create the AndSelector here, a tuple might be enough
780
5b6c93816871 fix selector search and refactor auto-instantiation
sylvain.thenault@logilab.fr
parents: 760
diff changeset
   712
    selector = AndSelector(*selectors)
693
cf0817dfc787 reimplements chainall/chainfirst using [And/Or], implemenent search_selector function on Selector base class
sylvain.thenault@logilab.fr
parents: 686
diff changeset
   713
    if 'name' in kwargs:
cf0817dfc787 reimplements chainall/chainfirst using [And/Or], implemenent search_selector function on Selector base class
sylvain.thenault@logilab.fr
parents: 686
diff changeset
   714
        selector.__name__ = kwargs['name']
cf0817dfc787 reimplements chainall/chainfirst using [And/Or], implemenent search_selector function on Selector base class
sylvain.thenault@logilab.fr
parents: 686
diff changeset
   715
    return selector
cf0817dfc787 reimplements chainall/chainfirst using [And/Or], implemenent search_selector function on Selector base class
sylvain.thenault@logilab.fr
parents: 686
diff changeset
   716
cf0817dfc787 reimplements chainall/chainfirst using [And/Or], implemenent search_selector function on Selector base class
sylvain.thenault@logilab.fr
parents: 686
diff changeset
   717
def chainfirst(*selectors, **kwargs):
cf0817dfc787 reimplements chainall/chainfirst using [And/Or], implemenent search_selector function on Selector base class
sylvain.thenault@logilab.fr
parents: 686
diff changeset
   718
    """return a selector chaining given selectors. If all
cf0817dfc787 reimplements chainall/chainfirst using [And/Or], implemenent search_selector function on Selector base class
sylvain.thenault@logilab.fr
parents: 686
diff changeset
   719
    the selectors fail, selection will fail, else the returned score
cf0817dfc787 reimplements chainall/chainfirst using [And/Or], implemenent search_selector function on Selector base class
sylvain.thenault@logilab.fr
parents: 686
diff changeset
   720
    will be the first non-zero selector score
cf0817dfc787 reimplements chainall/chainfirst using [And/Or], implemenent search_selector function on Selector base class
sylvain.thenault@logilab.fr
parents: 686
diff changeset
   721
    """
cf0817dfc787 reimplements chainall/chainfirst using [And/Or], implemenent search_selector function on Selector base class
sylvain.thenault@logilab.fr
parents: 686
diff changeset
   722
    assert selectors
780
5b6c93816871 fix selector search and refactor auto-instantiation
sylvain.thenault@logilab.fr
parents: 760
diff changeset
   723
    selector = OrSelector(*selectors)
693
cf0817dfc787 reimplements chainall/chainfirst using [And/Or], implemenent search_selector function on Selector base class
sylvain.thenault@logilab.fr
parents: 686
diff changeset
   724
    if 'name' in kwargs:
cf0817dfc787 reimplements chainall/chainfirst using [And/Or], implemenent search_selector function on Selector base class
sylvain.thenault@logilab.fr
parents: 686
diff changeset
   725
        selector.__name__ = kwargs['name']
cf0817dfc787 reimplements chainall/chainfirst using [And/Or], implemenent search_selector function on Selector base class
sylvain.thenault@logilab.fr
parents: 686
diff changeset
   726
    return selector