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