vregistry.py
author sylvain.thenault@logilab.fr
Wed, 11 Mar 2009 11:02:32 +0100
branchtls-sprint
changeset 1045 5040a5835e4d
parent 946 a130b5ceeca9
child 1046 52ee022d87e3
permissions -rw-r--r--
accept req as parameter for convenience
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):
943
9fdfa8d38359 [selectors] for bacwkard compatibility, we must search the mro, not just the current class, in order not to miss __selectors__ in classes that do not redefine it
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 835
diff changeset
   129
        for klass in cls.mro():
9fdfa8d38359 [selectors] for bacwkard compatibility, we must search the mro, not just the current class, in order not to miss __selectors__ in classes that do not redefine it
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 835
diff changeset
   130
            if klass.__name__ == 'AppRsetObject':
9fdfa8d38359 [selectors] for bacwkard compatibility, we must search the mro, not just the current class, in order not to miss __selectors__ in classes that do not redefine it
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 835
diff changeset
   131
                continue # the bw compat __selector__ is there
9fdfa8d38359 [selectors] for bacwkard compatibility, we must search the mro, not just the current class, in order not to miss __selectors__ in classes that do not redefine it
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 835
diff changeset
   132
            klassdict = klass.__dict__
9fdfa8d38359 [selectors] for bacwkard compatibility, we must search the mro, not just the current class, in order not to miss __selectors__ in classes that do not redefine it
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 835
diff changeset
   133
            if ('__select__' in klassdict and '__selectors__' in klassdict
9fdfa8d38359 [selectors] for bacwkard compatibility, we must search the mro, not just the current class, in order not to miss __selectors__ in classes that do not redefine it
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 835
diff changeset
   134
                and '__selgenerated__' not in klassdict):
9fdfa8d38359 [selectors] for bacwkard compatibility, we must search the mro, not just the current class, in order not to miss __selectors__ in classes that do not redefine it
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 835
diff changeset
   135
                raise TypeError("__select__ and __selectors__ can't be used together on class %s" % cls)
9fdfa8d38359 [selectors] for bacwkard compatibility, we must search the mro, not just the current class, in order not to miss __selectors__ in classes that do not redefine it
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 835
diff changeset
   136
            if '__selectors__' in klassdict and '__selgenerated__' not in klassdict:
9fdfa8d38359 [selectors] for bacwkard compatibility, we must search the mro, not just the current class, in order not to miss __selectors__ in classes that do not redefine it
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 835
diff changeset
   137
                cls.__selgenerated__ = True
9fdfa8d38359 [selectors] for bacwkard compatibility, we must search the mro, not just the current class, in order not to miss __selectors__ in classes that do not redefine it
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 835
diff changeset
   138
                # case where __selectors__ is defined locally (but __select__
9fdfa8d38359 [selectors] for bacwkard compatibility, we must search the mro, not just the current class, in order not to miss __selectors__ in classes that do not redefine it
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 835
diff changeset
   139
                # is in a parent class)
9fdfa8d38359 [selectors] for bacwkard compatibility, we must search the mro, not just the current class, in order not to miss __selectors__ in classes that do not redefine it
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 835
diff changeset
   140
                selectors = klassdict['__selectors__']
9fdfa8d38359 [selectors] for bacwkard compatibility, we must search the mro, not just the current class, in order not to miss __selectors__ in classes that do not redefine it
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 835
diff changeset
   141
                if len(selectors) == 1:
9fdfa8d38359 [selectors] for bacwkard compatibility, we must search the mro, not just the current class, in order not to miss __selectors__ in classes that do not redefine it
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 835
diff changeset
   142
                    # micro optimization: don't bother with AndSelector if there's
9fdfa8d38359 [selectors] for bacwkard compatibility, we must search the mro, not just the current class, in order not to miss __selectors__ in classes that do not redefine it
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 835
diff changeset
   143
                    # only one selector
9fdfa8d38359 [selectors] for bacwkard compatibility, we must search the mro, not just the current class, in order not to miss __selectors__ in classes that do not redefine it
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 835
diff changeset
   144
                    select = _instantiate_selector(selectors[0])
9fdfa8d38359 [selectors] for bacwkard compatibility, we must search the mro, not just the current class, in order not to miss __selectors__ in classes that do not redefine it
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 835
diff changeset
   145
                else:
9fdfa8d38359 [selectors] for bacwkard compatibility, we must search the mro, not just the current class, in order not to miss __selectors__ in classes that do not redefine it
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 835
diff changeset
   146
                    select = AndSelector(*selectors)
9fdfa8d38359 [selectors] for bacwkard compatibility, we must search the mro, not just the current class, in order not to miss __selectors__ in classes that do not redefine it
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 835
diff changeset
   147
                cls.__select__ = select
712
ce49e3885453 remove autoselectors metaclass, __select__ is built during registration
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 711
diff changeset
   148
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   149
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   150
class VRegistry(object):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   151
    """class responsible to register, propose and select the various
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   152
    elements used to build the web interface. Currently, we have templates,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   153
    views, actions and components.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   154
    """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   155
    
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   156
    def __init__(self, config):#, cache_size=1000):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   157
        self.config = config
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   158
        # dictionnary of registry (themself dictionnary) by name
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   159
        self._registries = {}
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   160
        self._lastmodifs = {}
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   161
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   162
    def reset(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   163
        self._registries = {}
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   164
        self._lastmodifs = {}
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 __getitem__(self, key):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   167
        return self._registries[key]
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 get(self, key, default=None):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   170
        return self._registries.get(key, default)
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 items(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   173
        return self._registries.items()
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 values(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   176
        return self._registries.values()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   177
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   178
    def __contains__(self, key):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   179
        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
   180
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   181
    def registry(self, name):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   182
        """return the registry (dictionary of class objects) associated to
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   183
        this name
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   184
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   185
        try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   186
            return self._registries[name]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   187
        except KeyError:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   188
            raise RegistryNotFound(name), None, sys.exc_info()[-1]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   189
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   190
    def registry_objects(self, name, oid=None):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   191
        """returns objects registered with the given oid in the given registry.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   192
        If no oid is given, return all objects in this registry
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   193
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   194
        registry = self.registry(name)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   195
        if oid:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   196
            try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   197
                return registry[oid]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   198
            except KeyError:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   199
                raise ObjectNotFound(oid), None, sys.exc_info()[-1]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   200
        else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   201
            result = []
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   202
            for objs in registry.values():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   203
                result += objs
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   204
            return result
665
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   205
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   206
    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
   207
        """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
   208
        objects = self[registry][cid]
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   209
        assert len(objects) == 1, objects
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   210
        return objects[0].selected(*args, **kwargs)
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   211
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   212
    # methods for explicit (un)registration ###################################
668
61b2328f9ed9 rename registration callback, clear argument to register
sylvain.thenault@logilab.fr
parents: 665
diff changeset
   213
61b2328f9ed9 rename registration callback, clear argument to register
sylvain.thenault@logilab.fr
parents: 665
diff changeset
   214
#     def clear(self, key):
61b2328f9ed9 rename registration callback, clear argument to register
sylvain.thenault@logilab.fr
parents: 665
diff changeset
   215
#         regname, oid = key.split('.')
61b2328f9ed9 rename registration callback, clear argument to register
sylvain.thenault@logilab.fr
parents: 665
diff changeset
   216
#         self[regname].pop(oid, None)
695
356da23c57f1 try a register_all method
sylvain.thenault@logilab.fr
parents: 693
diff changeset
   217
    def register_all(self, objects, modname, butclasses=()):
356da23c57f1 try a register_all method
sylvain.thenault@logilab.fr
parents: 693
diff changeset
   218
        for obj in objects:
356da23c57f1 try a register_all method
sylvain.thenault@logilab.fr
parents: 693
diff changeset
   219
            try:
356da23c57f1 try a register_all method
sylvain.thenault@logilab.fr
parents: 693
diff changeset
   220
                if obj.__module__ != modname or obj in butclasses:
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
                oid = obj.id
356da23c57f1 try a register_all method
sylvain.thenault@logilab.fr
parents: 693
diff changeset
   223
            except AttributeError:
356da23c57f1 try a register_all method
sylvain.thenault@logilab.fr
parents: 693
diff changeset
   224
                continue
356da23c57f1 try a register_all method
sylvain.thenault@logilab.fr
parents: 693
diff changeset
   225
            if oid:
356da23c57f1 try a register_all method
sylvain.thenault@logilab.fr
parents: 693
diff changeset
   226
                self.register(obj)
356da23c57f1 try a register_all method
sylvain.thenault@logilab.fr
parents: 693
diff changeset
   227
                
668
61b2328f9ed9 rename registration callback, clear argument to register
sylvain.thenault@logilab.fr
parents: 665
diff changeset
   228
    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
   229
        """base method to add an object in the registry"""
707
21a59b468f1a __selectors__ -> __select__
sylvain.thenault@logilab.fr
parents: 698
diff changeset
   230
        assert not '__abstract__' in obj.__dict__
665
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   231
        registryname = registryname or obj.__registry__
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   232
        oid = oid or obj.id
739
39721e56b56d assert oid
sylvain.thenault@logilab.fr
parents: 736
diff changeset
   233
        assert oid
665
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   234
        registry = self._registries.setdefault(registryname, {})
668
61b2328f9ed9 rename registration callback, clear argument to register
sylvain.thenault@logilab.fr
parents: 665
diff changeset
   235
        if clear:
61b2328f9ed9 rename registration callback, clear argument to register
sylvain.thenault@logilab.fr
parents: 665
diff changeset
   236
            vobjects = registry[oid] =  []
61b2328f9ed9 rename registration callback, clear argument to register
sylvain.thenault@logilab.fr
parents: 665
diff changeset
   237
        else:
61b2328f9ed9 rename registration callback, clear argument to register
sylvain.thenault@logilab.fr
parents: 665
diff changeset
   238
            vobjects = registry.setdefault(oid, [])
665
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   239
        # 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
   240
        # as such because we need to compose registered in some cases
682
sylvain.thenault@logilab.fr
parents: 673
diff changeset
   241
        vobject = obj.registered.im_func(obj, self)
665
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   242
        assert not vobject in vobjects
804
cc339d3ff7ae assert __select__ is callable
sylvain.thenault@logilab.fr
parents: 780
diff changeset
   243
        assert callable(vobject.__select__), vobject
665
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   244
        vobjects.append(vobject)
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   245
        try:
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   246
            vname = vobject.__name__
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   247
        except AttributeError:
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   248
            vname = vobject.__class__.__name__
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   249
        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
   250
                   vname, registryname, oid)
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   251
        # automatic reloading management
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   252
        self._registered['%s.%s' % (obj.__module__, oid)] = obj
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   253
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   254
    def unregister(self, obj, registryname=None):
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   255
        registryname = registryname or obj.__registry__
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   256
        registry = self.registry(registryname)
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   257
        removed_id = obj.classid()
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   258
        for registered in registry[obj.id]:
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   259
            # 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
   260
            # 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
   261
            if registered.classid() == removed_id:
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   262
                # XXX automatic reloading management
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   263
                try:
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   264
                    registry[obj.id].remove(registered)
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, no id %s in the %s registry',
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   267
                                 removed_id, obj.id, registryname)
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   268
                except ValueError:
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   269
                    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
   270
                                 removed_id, registryname, obj.id)
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   271
#                 else:
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   272
#                     # if objects is empty, remove oid from registry
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   273
#                     if not registry[obj.id]:
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   274
#                         del regcontent[oid]                    
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   275
                break
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   276
    
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   277
    def register_and_replace(self, obj, replaced, registryname=None):
673
64c50cb17d70 factorized impl
sylvain.thenault@logilab.fr
parents: 668
diff changeset
   278
        if hasattr(replaced, 'classid'):
64c50cb17d70 factorized impl
sylvain.thenault@logilab.fr
parents: 668
diff changeset
   279
            replaced = replaced.classid()
665
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   280
        registryname = registryname or obj.__registry__
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   281
        registry = self.registry(registryname)
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   282
        registered_objs = registry[obj.id]
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   283
        for index, registered in enumerate(registered_objs):
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   284
            if registered.classid() == replaced:
673
64c50cb17d70 factorized impl
sylvain.thenault@logilab.fr
parents: 668
diff changeset
   285
                del registry[obj.id][index]
64c50cb17d70 factorized impl
sylvain.thenault@logilab.fr
parents: 668
diff changeset
   286
                break
64c50cb17d70 factorized impl
sylvain.thenault@logilab.fr
parents: 668
diff changeset
   287
        self.register(obj, registryname=registryname)
665
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   288
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   289
    # dynamic selection methods ###############################################
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   290
    
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   291
    def select(self, vobjects, *args, **kwargs):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   292
        """return an instance of the most specific object according
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   293
        to parameters
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   294
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   295
        raise NoSelectableObject if not object apply
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   296
        """
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
   297
        score, winners = 0, []
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   298
        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
   299
            vobjectscore = vobject.__select__(vobject, *args, **kwargs)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   300
            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
   301
                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
   302
            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
   303
                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
   304
        if not winners:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   305
            raise NoSelectableObject('args: %s\nkwargs: %s %s'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   306
                                     % (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
   307
        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
   308
            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
   309
                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
   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
            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
   312
                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
   313
                                % (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
   314
        winner = winners[0]
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   315
        # return the result of the .selected method of the vobject
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   316
        return winner.selected(*args, **kwargs)
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
    def possible_objects(self, registry, *args, **kwargs):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   319
        """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
   320
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   321
        actions returned are classes, not instances
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   322
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   323
        for vobjects in self.registry(registry).values():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   324
            try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   325
                yield self.select(vobjects, *args, **kwargs)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   326
            except NoSelectableObject:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   327
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   328
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   329
    def select_object(self, registry, cid, *args, **kwargs):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   330
        """return the most specific component according to the resultset"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   331
        return self.select(self.registry_objects(registry, cid), *args, **kwargs)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   332
    
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   333
    # intialization methods ###################################################
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   334
    
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   335
    def register_objects(self, path, force_reload=None):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   336
        if force_reload is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   337
            force_reload = self.config.mode == 'dev'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   338
        elif not force_reload:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   339
            # force_reload == False usually mean modules have been reloaded
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   340
            # by another connection, so we want to update the registry
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   341
            # content even if there has been no module content modification
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   342
            self.reset()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   343
        # 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
   344
        # having the same module loaded as 'cubicweb.web.views' subpackage and
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   345
        # as views'  or 'web.views' subpackage
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   346
        # this is mainly for testing purpose, we should'nt need this in
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   347
        # production environment
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   348
        for webdir in (join(dirname(realpath(__file__)), 'web'),
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   349
                       join(dirname(__file__), 'web')):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   350
            if webdir in sys.path:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   351
                sys.path.remove(webdir)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   352
        if CW_SOFTWARE_ROOT in sys.path:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   353
            sys.path.remove(CW_SOFTWARE_ROOT)        
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   354
        # load views from each directory in the application's path
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   355
        change = False
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   356
        for fileordirectory in path:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   357
            if isdir(fileordirectory):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   358
                if self.read_directory(fileordirectory, force_reload):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   359
                    change = True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   360
            else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   361
                directory, filename = split(fileordirectory)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   362
                if self.load_file(directory, filename, force_reload):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   363
                    change = True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   364
        if change:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   365
            for registry, objects in self.items():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   366
                self.debug('available in registry %s: %s', registry,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   367
                           sorted(objects))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   368
        return change
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   369
    
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   370
    def read_directory(self, directory, force_reload=False):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   371
        """read a directory and register available views"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   372
        modified_on = stat(realpath(directory))[-2]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   373
        # only read directory if it was modified
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   374
        _lastmodifs = self._lastmodifs
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   375
        if directory in _lastmodifs and modified_on <= _lastmodifs[directory]:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   376
            return False
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   377
        self.info('loading directory %s', directory)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   378
        for filename in listdir(directory):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   379
            if filename[-3:] == '.py':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   380
                try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   381
                    self.load_file(directory, filename, force_reload)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   382
                except OSError:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   383
                    # this typically happens on emacs backup files (.#foo.py)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   384
                    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
   385
                                 filename)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   386
                except Exception, ex:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   387
                    if self.config.mode in ('dev', 'test'):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   388
                        raise
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   389
                    self.exception('%r while loading file %s', ex, filename)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   390
        _lastmodifs[directory] = modified_on
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   391
        return True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   392
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   393
    def load_file(self, directory, filename, force_reload=False):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   394
        """load visual objects from a python file"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   395
        from logilab.common.modutils import load_module_from_modpath, modpath_from_file
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   396
        filepath = join(directory, filename)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   397
        modified_on = stat(filepath)[-2]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   398
        modpath = modpath_from_file(join(directory, filename))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   399
        modname = '.'.join(modpath)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   400
        unregistered = {}
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   401
        _lastmodifs = self._lastmodifs
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   402
        if filepath in _lastmodifs:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   403
            # only load file if it was modified
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   404
            if modified_on <= _lastmodifs[filepath]:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   405
                return
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   406
            else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   407
                # if it was modified, unregister all exisiting objects
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   408
                # from this module, and keep track of what was unregistered
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   409
                unregistered = self.unregister_module_vobjects(modname)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   410
        # load the module
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   411
        module = load_module_from_modpath(modpath, use_sys=not force_reload)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   412
        registered = self.load_module(module)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   413
        # if something was unregistered, we need to update places where it was
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   414
        # referenced 
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   415
        if unregistered:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   416
            # oldnew_mapping = {}
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   417
            oldnew_mapping = dict((unregistered[name], registered[name])
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   418
                                  for name in unregistered if name in registered)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   419
            self.update_registered_subclasses(oldnew_mapping)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   420
        _lastmodifs[filepath] = modified_on
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   421
        return True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   422
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   423
    def load_module(self, module):
665
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   424
        self._registered = {}
668
61b2328f9ed9 rename registration callback, clear argument to register
sylvain.thenault@logilab.fr
parents: 665
diff changeset
   425
        if hasattr(module, 'registration_callback'):
61b2328f9ed9 rename registration callback, clear argument to register
sylvain.thenault@logilab.fr
parents: 665
diff changeset
   426
            module.registration_callback(self)
660
5233a9457f6b work in progress, draft for manual registration
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 652
diff changeset
   427
        else:
5233a9457f6b work in progress, draft for manual registration
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 652
diff changeset
   428
            self.info('loading %s', module)
5233a9457f6b work in progress, draft for manual registration
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 652
diff changeset
   429
            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
   430
                if objname.startswith('_'):
5233a9457f6b work in progress, draft for manual registration
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 652
diff changeset
   431
                    continue
665
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   432
                self.load_ancestors_then_object(module.__name__, obj)
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   433
        return self._registered
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   434
    
665
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   435
    def load_ancestors_then_object(self, modname, obj):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   436
        # skip imported classes
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   437
        if getattr(obj, '__module__', None) != modname:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   438
            return
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   439
        # skip non registerable object
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   440
        try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   441
            if not issubclass(obj, VObject):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   442
                return
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   443
        except TypeError:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   444
            return
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   445
        objname = '%s.%s' % (modname, obj.__name__)
665
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   446
        if objname in self._registered:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   447
            return
665
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   448
        self._registered[objname] = obj
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   449
        for parent in obj.__bases__:
665
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   450
            self.load_ancestors_then_object(modname, parent)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   451
        self.load_object(obj)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   452
            
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   453
    def load_object(self, obj):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   454
        try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   455
            self.register_vobject_class(obj)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   456
        except Exception, ex:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   457
            if self.config.mode in ('test', 'dev'):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   458
                raise
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   459
            self.exception('vobject %s registration failed: %s', obj, ex)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   460
        
665
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   461
    # old automatic registration XXX deprecated ###############################
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
    def register_vobject_class(self, cls):
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   464
        """handle vobject class registration
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   465
        
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   466
        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
   467
        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
   468
        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
   469
        to a non empty string to be registered.
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   470
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   471
        Registration is actually handled by vobject's registerer.
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   472
        """
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   473
        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
   474
            or not cls.__registry__ or not cls.id):
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
        regname = cls.__registry__
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   477
        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
   478
            return
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   479
        registry = self._registries.setdefault(regname, {})
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   480
        vobjects = registry.setdefault(cls.id, [])
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   481
        registerer = cls.__registerer__(self, cls)
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   482
        cls = registerer.do_it_yourself(vobjects)
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   483
        if cls:
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   484
            self.register(cls)
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
    def unregister_module_vobjects(self, modname):
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   487
        """removes registered objects coming from a given module
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   488
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   489
        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
   490
        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
   491
        in the <modname> module)
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   492
        """
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   493
        unregistered = {}
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   494
        # browse each registered object
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   495
        for registry, objdict in self.items():
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   496
            for oid, objects in objdict.items():
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   497
                for obj in objects[:]:
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   498
                    objname = obj.classid()
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   499
                    # 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
   500
                    if objname.startswith(modname):
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   501
                        unregistered[objname] = obj
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   502
                        objects.remove(obj)
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   503
                        self.debug('unregistering %s in %s registry',
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   504
                                  objname, registry)
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   505
                    # 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
   506
                    # (because we also want subclasses to be updated)
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   507
                    else:
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   508
                        if not isinstance(obj, type):
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   509
                            obj = obj.__class__
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   510
                        for baseclass in obj.__bases__:
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   511
                            if hasattr(baseclass, 'classid'):
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   512
                                baseclassid = baseclass.classid()
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   513
                                if baseclassid.startswith(modname):
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   514
                                    unregistered[baseclassid] = baseclass
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   515
                # update oid entry
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   516
                if objects:
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   517
                    objdict[oid] = objects
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   518
                else:
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   519
                    del objdict[oid]
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   520
        return unregistered
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
    def update_registered_subclasses(self, oldnew_mapping):
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   523
        """updates subclasses of re-registered vobjects
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   524
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   525
        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
   526
        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
   527
        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
   528
        that's what this method does
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
        :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
   531
                               the new version
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   532
        """
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   533
        # browse each registered object
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   534
        for objdict in self.values():
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   535
            for objects in objdict.values():
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   536
                for obj in objects:
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   537
                    if not isinstance(obj, type):
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   538
                        obj = obj.__class__
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   539
                    # build new baseclasses tuple
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   540
                    newbases = tuple(oldnew_mapping.get(baseclass, baseclass)
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   541
                                     for baseclass in obj.__bases__)
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   542
                    # update obj's baseclasses tuple (__bases__) if needed
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   543
                    if newbases != obj.__bases__:
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   544
                        self.debug('updating %s.%s base classes',
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   545
                                  obj.__module__, obj.__name__)
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   546
                        obj.__bases__ = newbases
1305da1ce3f9 reorganize a bit, some cleanup and fixes
sylvain.thenault@logilab.fr
parents: 660
diff changeset
   547
        
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   548
# init logging 
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   549
set_log_methods(VObject, getLogger('cubicweb'))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   550
set_log_methods(VRegistry, getLogger('cubicweb.registry'))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   551
set_log_methods(registerer, getLogger('cubicweb.registration'))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   552
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   553
630
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   554
# 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
   555
630
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   556
class Selector(object):
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   557
    """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
   558
    for operators ``&`` and ``|``
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   559
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   560
    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
   561
    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
   562
f7011679437a doc update, move yes_registerer here
sylvain.thenault@logilab.fr
parents: 714
diff changeset
   563
f7011679437a doc update, move yes_registerer here
sylvain.thenault@logilab.fr
parents: 714
diff changeset
   564
    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
   565
    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
   566
    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
   567
f7011679437a doc update, move yes_registerer here
sylvain.thenault@logilab.fr
parents: 714
diff changeset
   568
    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
   569
    """
698
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   570
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
   571
    @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
   572
    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
   573
        # 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
   574
        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
   575
698
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   576
    def search_selector(self, selector):
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   577
        """search for the given selector or selector instance in the selectors
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   578
        tree. Return it of None if not found
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   579
        """
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   580
        if self is selector:
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   581
            return self
721
sylvain.thenault@logilab.fr
parents: 719
diff changeset
   582
        if isinstance(selector, type) and isinstance(self, selector):
698
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   583
            return self
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   584
        return None
780
5b6c93816871 fix selector search and refactor auto-instantiation
sylvain.thenault@logilab.fr
parents: 760
diff changeset
   585
5b6c93816871 fix selector search and refactor auto-instantiation
sylvain.thenault@logilab.fr
parents: 760
diff changeset
   586
    def __str__(self):
5b6c93816871 fix selector search and refactor auto-instantiation
sylvain.thenault@logilab.fr
parents: 760
diff changeset
   587
        return self.__class__.__name__
698
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   588
    
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   589
    def __and__(self, other):
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   590
        return AndSelector(self, other)
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   591
    def __rand__(self, other):
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   592
        return AndSelector(other, self)
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   593
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   594
    def __or__(self, other):
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   595
        return OrSelector(self, other)
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   596
    def __ror__(self, other):
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   597
        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
   598
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
   599
    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
   600
        return NotSelector(self)
698
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   601
    
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   602
    # XXX (function | function) or (function & function) not managed yet
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   603
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   604
    def __call__(self, cls, *args, **kwargs):
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   605
        return NotImplementedError("selector %s must implement its logic "
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   606
                                   "in its __call__ method" % self.__class__)
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   607
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   608
class MultiSelector(Selector):
718
f7011679437a doc update, move yes_registerer here
sylvain.thenault@logilab.fr
parents: 714
diff changeset
   609
    """base class for compound selector classes"""
f7011679437a doc update, move yes_registerer here
sylvain.thenault@logilab.fr
parents: 714
diff changeset
   610
    
630
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   611
    def __init__(self, *selectors):
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   612
        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
   613
780
5b6c93816871 fix selector search and refactor auto-instantiation
sylvain.thenault@logilab.fr
parents: 760
diff changeset
   614
    def __str__(self):
5b6c93816871 fix selector search and refactor auto-instantiation
sylvain.thenault@logilab.fr
parents: 760
diff changeset
   615
        return '%s(%s)' % (self.__class__.__name__,
5b6c93816871 fix selector search and refactor auto-instantiation
sylvain.thenault@logilab.fr
parents: 760
diff changeset
   616
                           ','.join(str(s) for s in self.selectors))
5b6c93816871 fix selector search and refactor auto-instantiation
sylvain.thenault@logilab.fr
parents: 760
diff changeset
   617
630
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   618
    @classmethod
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   619
    def merge_selectors(cls, selectors):
780
5b6c93816871 fix selector search and refactor auto-instantiation
sylvain.thenault@logilab.fr
parents: 760
diff changeset
   620
        """deal with selector instanciation when necessary and merge
5b6c93816871 fix selector search and refactor auto-instantiation
sylvain.thenault@logilab.fr
parents: 760
diff changeset
   621
        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
   622
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   623
        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
   624
        ==> 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
   625
        """
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   626
        merged_selectors = []
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   627
        for selector in selectors:
946
a130b5ceeca9 [selectors] _needs real fix_ whack 'till it works for me
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 943
diff changeset
   628
            try:
a130b5ceeca9 [selectors] _needs real fix_ whack 'till it works for me
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 943
diff changeset
   629
                selector = _instantiate_selector(selector)
a130b5ceeca9 [selectors] _needs real fix_ whack 'till it works for me
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 943
diff changeset
   630
            except:
a130b5ceeca9 [selectors] _needs real fix_ whack 'till it works for me
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 943
diff changeset
   631
                pass
a130b5ceeca9 [selectors] _needs real fix_ whack 'till it works for me
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 943
diff changeset
   632
            #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
   633
            if isinstance(selector, cls):
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   634
                merged_selectors += selector.selectors
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   635
            else:
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   636
                merged_selectors.append(selector)
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   637
        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
   638
cf0817dfc787 reimplements chainall/chainfirst using [And/Or], implemenent search_selector function on Selector base class
sylvain.thenault@logilab.fr
parents: 686
diff changeset
   639
    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
   640
        """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
   641
        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
   642
        """
cf0817dfc787 reimplements chainall/chainfirst using [And/Or], implemenent search_selector function on Selector base class
sylvain.thenault@logilab.fr
parents: 686
diff changeset
   643
        for childselector in self.selectors:
780
5b6c93816871 fix selector search and refactor auto-instantiation
sylvain.thenault@logilab.fr
parents: 760
diff changeset
   644
            if childselector is selector:
5b6c93816871 fix selector search and refactor auto-instantiation
sylvain.thenault@logilab.fr
parents: 760
diff changeset
   645
                return childselector
5b6c93816871 fix selector search and refactor auto-instantiation
sylvain.thenault@logilab.fr
parents: 760
diff changeset
   646
            found = childselector.search_selector(selector)
5b6c93816871 fix selector search and refactor auto-instantiation
sylvain.thenault@logilab.fr
parents: 760
diff changeset
   647
            if found is not None:
5b6c93816871 fix selector search and refactor auto-instantiation
sylvain.thenault@logilab.fr
parents: 760
diff changeset
   648
                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
   649
        return None
630
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   650
697
06807984e610 provide objectify_selector decorator for very simple selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 695
diff changeset
   651
    
06807984e610 provide objectify_selector decorator for very simple selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 695
diff changeset
   652
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
   653
    """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
   654
    would be overkill::
06807984e610 provide objectify_selector decorator for very simple selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 695
diff changeset
   655
06807984e610 provide objectify_selector decorator for very simple selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 695
diff changeset
   656
        @objectify_selector
06807984e610 provide objectify_selector decorator for very simple selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 695
diff changeset
   657
        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
   658
            return 1
06807984e610 provide objectify_selector decorator for very simple selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 695
diff changeset
   659
        
06807984e610 provide objectify_selector decorator for very simple selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 695
diff changeset
   660
    """
06807984e610 provide objectify_selector decorator for very simple selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 695
diff changeset
   661
    return type(selector_func.__name__, (Selector,),
734
4153a82a60a4 get kwargs as well
sylvain.thenault@logilab.fr
parents: 727
diff changeset
   662
                {'__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
   663
712
ce49e3885453 remove autoselectors metaclass, __select__ is built during registration
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 711
diff changeset
   664
def _instantiate_selector(selector):
ce49e3885453 remove autoselectors metaclass, __select__ is built during registration
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 711
diff changeset
   665
    """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
   666
    
ce49e3885453 remove autoselectors metaclass, __select__ is built during registration
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 711
diff changeset
   667
    NOTE: This should only be used locally in build___select__()
946
a130b5ceeca9 [selectors] _needs real fix_ whack 'till it works for me
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 943
diff changeset
   668
    XXX: then, why not do it ??
712
ce49e3885453 remove autoselectors metaclass, __select__ is built during registration
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 711
diff changeset
   669
    """
ce49e3885453 remove autoselectors metaclass, __select__ is built during registration
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 711
diff changeset
   670
    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
   671
        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
   672
    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
   673
        return selector()
ce49e3885453 remove autoselectors metaclass, __select__ is built during registration
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 711
diff changeset
   674
    return selector
ce49e3885453 remove autoselectors metaclass, __select__ is built during registration
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 711
diff changeset
   675
630
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   676
698
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   677
class AndSelector(MultiSelector):
630
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   678
    """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
   679
    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
   680
        score = 0
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   681
        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
   682
            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
   683
            if not partscore:
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   684
                return 0
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   685
            score += partscore
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   686
        return score
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   687
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   688
698
7dfd03e9e810 introduce MultiSelector base class
sylvain.thenault@logilab.fr
parents: 697
diff changeset
   689
class OrSelector(MultiSelector):
630
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   690
    """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
   691
    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
   692
        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
   693
            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
   694
            if partscore:
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   695
                return partscore
66ff0b2f7d03 simple test implementation for binary operators on selectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 615
diff changeset
   696
        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
   697
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
   698
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
   699
    """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
   700
    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
   701
        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
   702
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
   703
    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
   704
        score = self.selector(cls, *args, **kwargs)
835
7dcb11dd443e fix relation_possible, ensure we return int
sylvain.thenault@logilab.fr
parents: 827
diff changeset
   705
        return int(not score)
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
   706
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
   707
    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
   708
        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
   709
835
7dcb11dd443e fix relation_possible, ensure we return int
sylvain.thenault@logilab.fr
parents: 827
diff changeset
   710
7dcb11dd443e fix relation_possible, ensure we return int
sylvain.thenault@logilab.fr
parents: 827
diff changeset
   711
# XXX bw compat functions #####################################################
693
cf0817dfc787 reimplements chainall/chainfirst using [And/Or], implemenent search_selector function on Selector base class
sylvain.thenault@logilab.fr
parents: 686
diff changeset
   712
cf0817dfc787 reimplements chainall/chainfirst using [And/Or], implemenent search_selector function on Selector base class
sylvain.thenault@logilab.fr
parents: 686
diff changeset
   713
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
   714
    """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
   715
    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
   716
    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
   717
    """
cf0817dfc787 reimplements chainall/chainfirst using [And/Or], implemenent search_selector function on Selector base class
sylvain.thenault@logilab.fr
parents: 686
diff changeset
   718
    assert selectors
759
e044f28372bd chainall / chainfirst ensures selectors are instantiated
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 741
diff changeset
   719
    # 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
   720
    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
   721
    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
   722
        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
   723
    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
   724
cf0817dfc787 reimplements chainall/chainfirst using [And/Or], implemenent search_selector function on Selector base class
sylvain.thenault@logilab.fr
parents: 686
diff changeset
   725
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
   726
    """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
   727
    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
   728
    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
   729
    """
cf0817dfc787 reimplements chainall/chainfirst using [And/Or], implemenent search_selector function on Selector base class
sylvain.thenault@logilab.fr
parents: 686
diff changeset
   730
    assert selectors
780
5b6c93816871 fix selector search and refactor auto-instantiation
sylvain.thenault@logilab.fr
parents: 760
diff changeset
   731
    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
   732
    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
   733
        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
   734
    return selector