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