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