cwvreg.py
author Sylvain Thénault <sylvain.thenault@logilab.fr>
Thu, 28 May 2009 18:31:14 +0200
changeset 1985 9c1db4e06095
parent 1977 606923dff11b
child 2025 010a4b0fe855
permissions -rw-r--r--
move view method's logic on the registry, so it's easier to call it from outside an appobject. Also make rset argument optional
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     1
"""extend the generic VRegistry with some cubicweb specific stuff
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     2
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     3
:organization: Logilab
1977
606923dff11b big bunch of copyright / docstring update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1923
diff changeset
     4
: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
     5
: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: 1923
diff changeset
     6
: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
     7
"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     8
__docformat__ = "restructuredtext en"
1769
fb91d2b8a441 fix some rtags pb on i18n catalog generation
sylvain.thenault@logilab.fr
parents: 1752
diff changeset
     9
_ = unicode
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    10
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    11
from logilab.common.decorators import cached, clear_cache
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    12
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    13
from rql import RQLHelper
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    14
1923
3802c2e37e72 handle speaking to an instance using old entity types
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1917
diff changeset
    15
from cubicweb import ETYPE_NAME_MAP, Binary, UnknownProperty, UnknownEid
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    16
from cubicweb.vregistry import VRegistry, ObjectNotFound, NoSelectableObject
1769
fb91d2b8a441 fix some rtags pb on i18n catalog generation
sylvain.thenault@logilab.fr
parents: 1752
diff changeset
    17
from cubicweb.rtags import RTAGS
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    18
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    19
776
29ba95ea7e7d no more used
sylvain.thenault@logilab.fr
parents: 717
diff changeset
    20
def use_interfaces(obj):
1132
96752791c2b6 pylint cleanup
sylvain.thenault@logilab.fr
parents: 1044
diff changeset
    21
    """return interfaces used by the given object by searchinf for implements
96752791c2b6 pylint cleanup
sylvain.thenault@logilab.fr
parents: 1044
diff changeset
    22
    selectors, with a bw compat fallback to accepts_interfaces attribute
96752791c2b6 pylint cleanup
sylvain.thenault@logilab.fr
parents: 1044
diff changeset
    23
    """
776
29ba95ea7e7d no more used
sylvain.thenault@logilab.fr
parents: 717
diff changeset
    24
    from cubicweb.selectors import implements
29ba95ea7e7d no more used
sylvain.thenault@logilab.fr
parents: 717
diff changeset
    25
    try:
29ba95ea7e7d no more used
sylvain.thenault@logilab.fr
parents: 717
diff changeset
    26
        # XXX deprecated
1475
5c1ec97f317e should not be necessary anymore to add entity class to __implements__
sylvain.thenault@logilab.fr
parents: 1357
diff changeset
    27
        return sorted(obj.accepts_interfaces)
776
29ba95ea7e7d no more used
sylvain.thenault@logilab.fr
parents: 717
diff changeset
    28
    except AttributeError:
29ba95ea7e7d no more used
sylvain.thenault@logilab.fr
parents: 717
diff changeset
    29
        try:
29ba95ea7e7d no more used
sylvain.thenault@logilab.fr
parents: 717
diff changeset
    30
            impl = obj.__select__.search_selector(implements)
29ba95ea7e7d no more used
sylvain.thenault@logilab.fr
parents: 717
diff changeset
    31
            if impl:
29ba95ea7e7d no more used
sylvain.thenault@logilab.fr
parents: 717
diff changeset
    32
                return sorted(impl.expected_ifaces)
29ba95ea7e7d no more used
sylvain.thenault@logilab.fr
parents: 717
diff changeset
    33
        except AttributeError:
29ba95ea7e7d no more used
sylvain.thenault@logilab.fr
parents: 717
diff changeset
    34
            pass # old-style vobject classes with no accepts_interfaces
1044
3672a7c86784 print message to help debugging selector on error
sylvain.thenault@logilab.fr
parents: 1037
diff changeset
    35
        except:
3672a7c86784 print message to help debugging selector on error
sylvain.thenault@logilab.fr
parents: 1037
diff changeset
    36
            print 'bad selector %s on %s' % (obj.__select__, obj)
3672a7c86784 print message to help debugging selector on error
sylvain.thenault@logilab.fr
parents: 1037
diff changeset
    37
            raise
776
29ba95ea7e7d no more used
sylvain.thenault@logilab.fr
parents: 717
diff changeset
    38
        return ()
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    39
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    40
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    41
class CubicWebRegistry(VRegistry):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    42
    """extend the generic VRegistry with some cubicweb specific stuff"""
1475
5c1ec97f317e should not be necessary anymore to add entity class to __implements__
sylvain.thenault@logilab.fr
parents: 1357
diff changeset
    43
169
0e031b66cb0b don't systematically init_log, it may breaks client log configuration
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 0
diff changeset
    44
    def __init__(self, config, debug=None, initlog=True):
0e031b66cb0b don't systematically init_log, it may breaks client log configuration
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 0
diff changeset
    45
        if initlog:
0e031b66cb0b don't systematically init_log, it may breaks client log configuration
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 0
diff changeset
    46
            # first init log service
0e031b66cb0b don't systematically init_log, it may breaks client log configuration
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 0
diff changeset
    47
            config.init_log(debug=debug)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    48
        super(CubicWebRegistry, self).__init__(config)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    49
        self.schema = None
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    50
        self.reset()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    51
        self.initialized = False
1475
5c1ec97f317e should not be necessary anymore to add entity class to __implements__
sylvain.thenault@logilab.fr
parents: 1357
diff changeset
    52
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    53
    def items(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    54
        return [item for item in self._registries.items()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    55
                if not item[0] in ('propertydefs', 'propertyvalues')]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    56
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    57
    def values(self):
1132
96752791c2b6 pylint cleanup
sylvain.thenault@logilab.fr
parents: 1044
diff changeset
    58
        return [value for key, value in self._registries.items()
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    59
                if not key in ('propertydefs', 'propertyvalues')]
1475
5c1ec97f317e should not be necessary anymore to add entity class to __implements__
sylvain.thenault@logilab.fr
parents: 1357
diff changeset
    60
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    61
    def reset(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    62
        self._registries = {}
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    63
        self._lastmodifs = {}
666
8ad9885ea45a interface handling should be done here
sylvain.thenault@logilab.fr
parents: 631
diff changeset
    64
        self._needs_iface = {}
8ad9885ea45a interface handling should be done here
sylvain.thenault@logilab.fr
parents: 631
diff changeset
    65
        # two special registries, propertydefs which care all the property
8ad9885ea45a interface handling should be done here
sylvain.thenault@logilab.fr
parents: 631
diff changeset
    66
        # definitions, and propertyvals which contains values for those
8ad9885ea45a interface handling should be done here
sylvain.thenault@logilab.fr
parents: 631
diff changeset
    67
        # properties
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    68
        self._registries['propertydefs'] = {}
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    69
        self._registries['propertyvalues'] = self.eprop_values = {}
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    70
        for key, propdef in self.config.eproperty_definitions():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    71
            self.register_property(key, **propdef)
1475
5c1ec97f317e should not be necessary anymore to add entity class to __implements__
sylvain.thenault@logilab.fr
parents: 1357
diff changeset
    72
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    73
    def set_schema(self, schema):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    74
        """set application'schema and load application objects"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    75
        self.schema = schema
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    76
        clear_cache(self, 'rqlhelper')
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    77
        # now we can load application's web objects
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    78
        self.register_objects(self.config.vregistry_path())
1475
5c1ec97f317e should not be necessary anymore to add entity class to __implements__
sylvain.thenault@logilab.fr
parents: 1357
diff changeset
    79
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    80
    def update_schema(self, schema):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    81
        """update .schema attribute on registered objects, necessary for some
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    82
        tests
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    83
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    84
        self.schema = schema
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    85
        for registry, regcontent in self._registries.items():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    86
            if registry in ('propertydefs', 'propertyvalues'):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    87
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    88
            for objects in regcontent.values():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    89
                for obj in objects:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    90
                    obj.schema = schema
666
8ad9885ea45a interface handling should be done here
sylvain.thenault@logilab.fr
parents: 631
diff changeset
    91
8ad9885ea45a interface handling should be done here
sylvain.thenault@logilab.fr
parents: 631
diff changeset
    92
    def register_if_interface_found(self, obj, ifaces, **kwargs):
8ad9885ea45a interface handling should be done here
sylvain.thenault@logilab.fr
parents: 631
diff changeset
    93
        """register an object but remove it if no entity class implements one of
8ad9885ea45a interface handling should be done here
sylvain.thenault@logilab.fr
parents: 631
diff changeset
    94
        the given interfaces
8ad9885ea45a interface handling should be done here
sylvain.thenault@logilab.fr
parents: 631
diff changeset
    95
        """
785
e4f9fa3c891a more iface based cleanup fixes
sylvain.thenault@logilab.fr
parents: 777
diff changeset
    96
        self.register(obj, **kwargs)
666
8ad9885ea45a interface handling should be done here
sylvain.thenault@logilab.fr
parents: 631
diff changeset
    97
        if not isinstance(ifaces,  (tuple, list)):
785
e4f9fa3c891a more iface based cleanup fixes
sylvain.thenault@logilab.fr
parents: 777
diff changeset
    98
            self._needs_iface[obj] = (ifaces,)
666
8ad9885ea45a interface handling should be done here
sylvain.thenault@logilab.fr
parents: 631
diff changeset
    99
        else:
785
e4f9fa3c891a more iface based cleanup fixes
sylvain.thenault@logilab.fr
parents: 777
diff changeset
   100
            self._needs_iface[obj] = ifaces
666
8ad9885ea45a interface handling should be done here
sylvain.thenault@logilab.fr
parents: 631
diff changeset
   101
8ad9885ea45a interface handling should be done here
sylvain.thenault@logilab.fr
parents: 631
diff changeset
   102
    def register(self, obj, **kwargs):
717
54b873918b48 kill id_registerer
sylvain.thenault@logilab.fr
parents: 666
diff changeset
   103
        if kwargs.get('registryname', obj.__registry__) == 'etypes':
1037
1f3fae8d82b2 don't fail if vobjects reference an unexistant class
sylvain.thenault@logilab.fr
parents: 1016
diff changeset
   104
            if obj.id != 'Any' and not obj.id in self.schema:
1132
96752791c2b6 pylint cleanup
sylvain.thenault@logilab.fr
parents: 1044
diff changeset
   105
                self.error('don\'t register %s, %s type not defined in the '
96752791c2b6 pylint cleanup
sylvain.thenault@logilab.fr
parents: 1044
diff changeset
   106
                           'schema', obj, obj.id)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   107
                return
717
54b873918b48 kill id_registerer
sylvain.thenault@logilab.fr
parents: 666
diff changeset
   108
            kwargs['clear'] = True
666
8ad9885ea45a interface handling should be done here
sylvain.thenault@logilab.fr
parents: 631
diff changeset
   109
        super(CubicWebRegistry, self).register(obj, **kwargs)
8ad9885ea45a interface handling should be done here
sylvain.thenault@logilab.fr
parents: 631
diff changeset
   110
        # XXX bw compat
777
39695e98ba35 test and fix interface based objects cleaning
sylvain.thenault@logilab.fr
parents: 776
diff changeset
   111
        ifaces = use_interfaces(obj)
666
8ad9885ea45a interface handling should be done here
sylvain.thenault@logilab.fr
parents: 631
diff changeset
   112
        if ifaces:
785
e4f9fa3c891a more iface based cleanup fixes
sylvain.thenault@logilab.fr
parents: 777
diff changeset
   113
            self._needs_iface[obj] = ifaces
1475
5c1ec97f317e should not be necessary anymore to add entity class to __implements__
sylvain.thenault@logilab.fr
parents: 1357
diff changeset
   114
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   115
    def register_objects(self, path, force_reload=None):
666
8ad9885ea45a interface handling should be done here
sylvain.thenault@logilab.fr
parents: 631
diff changeset
   116
        """overriden to remove objects requiring a missing interface"""
8ad9885ea45a interface handling should be done here
sylvain.thenault@logilab.fr
parents: 631
diff changeset
   117
        if super(CubicWebRegistry, self).register_objects(path, force_reload):
1638
6f9003a32ecc extract method
sylvain.thenault@logilab.fr
parents: 1513
diff changeset
   118
            self.initialization_completed()
1752
4b0b912ff5b7 fix rtags initialization: do it at the registry level to avoid multiple initialization of the same rtag
sylvain.thenault@logilab.fr
parents: 1723
diff changeset
   119
            # call vreg_initialization_completed on appobjects and print
4b0b912ff5b7 fix rtags initialization: do it at the registry level to avoid multiple initialization of the same rtag
sylvain.thenault@logilab.fr
parents: 1723
diff changeset
   120
            # registry content
1282
272d8ec6f308 * print vreg content once fully initialized (require move of print code from vregistry to cwvreg)
sylvain.thenault@logilab.fr
parents: 1263
diff changeset
   121
            for registry, objects in self.items():
272d8ec6f308 * print vreg content once fully initialized (require move of print code from vregistry to cwvreg)
sylvain.thenault@logilab.fr
parents: 1263
diff changeset
   122
                self.debug('available in registry %s: %s', registry,
272d8ec6f308 * print vreg content once fully initialized (require move of print code from vregistry to cwvreg)
sylvain.thenault@logilab.fr
parents: 1263
diff changeset
   123
                           sorted(objects))
272d8ec6f308 * print vreg content once fully initialized (require move of print code from vregistry to cwvreg)
sylvain.thenault@logilab.fr
parents: 1263
diff changeset
   124
                for appobjects in objects.itervalues():
272d8ec6f308 * print vreg content once fully initialized (require move of print code from vregistry to cwvreg)
sylvain.thenault@logilab.fr
parents: 1263
diff changeset
   125
                    for appobject in appobjects:
272d8ec6f308 * print vreg content once fully initialized (require move of print code from vregistry to cwvreg)
sylvain.thenault@logilab.fr
parents: 1263
diff changeset
   126
                        appobject.vreg_initialization_completed()
1769
fb91d2b8a441 fix some rtags pb on i18n catalog generation
sylvain.thenault@logilab.fr
parents: 1752
diff changeset
   127
            # don't check rtags if we don't want to cleanup_interface_sobjects
1752
4b0b912ff5b7 fix rtags initialization: do it at the registry level to avoid multiple initialization of the same rtag
sylvain.thenault@logilab.fr
parents: 1723
diff changeset
   128
            for rtag in RTAGS:
1769
fb91d2b8a441 fix some rtags pb on i18n catalog generation
sylvain.thenault@logilab.fr
parents: 1752
diff changeset
   129
                rtag.init(self.schema,
fb91d2b8a441 fix some rtags pb on i18n catalog generation
sylvain.thenault@logilab.fr
parents: 1752
diff changeset
   130
                          check=self.config.cleanup_interface_sobjects)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   131
1638
6f9003a32ecc extract method
sylvain.thenault@logilab.fr
parents: 1513
diff changeset
   132
    def initialization_completed(self):
6f9003a32ecc extract method
sylvain.thenault@logilab.fr
parents: 1513
diff changeset
   133
        # clear etype cache if you don't want to run into deep weirdness
6f9003a32ecc extract method
sylvain.thenault@logilab.fr
parents: 1513
diff changeset
   134
        clear_cache(self, 'etype_class')
6f9003a32ecc extract method
sylvain.thenault@logilab.fr
parents: 1513
diff changeset
   135
        # we may want to keep interface dependent objects (e.g.for i18n
6f9003a32ecc extract method
sylvain.thenault@logilab.fr
parents: 1513
diff changeset
   136
        # catalog generation)
6f9003a32ecc extract method
sylvain.thenault@logilab.fr
parents: 1513
diff changeset
   137
        if self.config.cleanup_interface_sobjects:
6f9003a32ecc extract method
sylvain.thenault@logilab.fr
parents: 1513
diff changeset
   138
            # remove vobjects that don't support any available interface
6f9003a32ecc extract method
sylvain.thenault@logilab.fr
parents: 1513
diff changeset
   139
            implemented_interfaces = set()
6f9003a32ecc extract method
sylvain.thenault@logilab.fr
parents: 1513
diff changeset
   140
            if 'Any' in self.get('etypes', ()):
6f9003a32ecc extract method
sylvain.thenault@logilab.fr
parents: 1513
diff changeset
   141
                for etype in self.schema.entities():
6f9003a32ecc extract method
sylvain.thenault@logilab.fr
parents: 1513
diff changeset
   142
                    cls = self.etype_class(etype)
6f9003a32ecc extract method
sylvain.thenault@logilab.fr
parents: 1513
diff changeset
   143
                    for iface in cls.__implements__:
6f9003a32ecc extract method
sylvain.thenault@logilab.fr
parents: 1513
diff changeset
   144
                        implemented_interfaces.update(iface.__mro__)
6f9003a32ecc extract method
sylvain.thenault@logilab.fr
parents: 1513
diff changeset
   145
                    implemented_interfaces.update(cls.__mro__)
6f9003a32ecc extract method
sylvain.thenault@logilab.fr
parents: 1513
diff changeset
   146
            for obj, ifaces in self._needs_iface.items():
6f9003a32ecc extract method
sylvain.thenault@logilab.fr
parents: 1513
diff changeset
   147
                ifaces = frozenset(isinstance(iface, basestring)
6f9003a32ecc extract method
sylvain.thenault@logilab.fr
parents: 1513
diff changeset
   148
                                   and iface in self.schema
6f9003a32ecc extract method
sylvain.thenault@logilab.fr
parents: 1513
diff changeset
   149
                                   and self.etype_class(iface)
6f9003a32ecc extract method
sylvain.thenault@logilab.fr
parents: 1513
diff changeset
   150
                                   or iface
6f9003a32ecc extract method
sylvain.thenault@logilab.fr
parents: 1513
diff changeset
   151
                                   for iface in ifaces)
6f9003a32ecc extract method
sylvain.thenault@logilab.fr
parents: 1513
diff changeset
   152
                if not ('Any' in ifaces or ifaces & implemented_interfaces):
6f9003a32ecc extract method
sylvain.thenault@logilab.fr
parents: 1513
diff changeset
   153
                    self.debug('kicking vobject %s (no implemented '
6f9003a32ecc extract method
sylvain.thenault@logilab.fr
parents: 1513
diff changeset
   154
                               'interface among %s)', obj, ifaces)
6f9003a32ecc extract method
sylvain.thenault@logilab.fr
parents: 1513
diff changeset
   155
                    self.unregister(obj)
6f9003a32ecc extract method
sylvain.thenault@logilab.fr
parents: 1513
diff changeset
   156
        # clear needs_iface so we don't try to remove some not-anymore-in
6f9003a32ecc extract method
sylvain.thenault@logilab.fr
parents: 1513
diff changeset
   157
        # objects on automatic reloading
6f9003a32ecc extract method
sylvain.thenault@logilab.fr
parents: 1513
diff changeset
   158
        self._needs_iface.clear()
6f9003a32ecc extract method
sylvain.thenault@logilab.fr
parents: 1513
diff changeset
   159
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   160
    @cached
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   161
    def etype_class(self, etype):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   162
        """return an entity class for the given entity type.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   163
        Try to find out a specific class for this kind of entity or
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   164
        default to a dump of the class registered for 'Any'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   165
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   166
        etype = str(etype)
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: 395
diff changeset
   167
        if etype == 'Any':
99f5852f8604 major selector refactoring (mostly to avoid looking for select parameters on the target class), start accept / interface unification)
sylvain.thenault@logilab.fr
parents: 395
diff changeset
   168
            return self.select(self.registry_objects('etypes', 'Any'), 'Any')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   169
        eschema = self.schema.eschema(etype)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   170
        baseschemas = [eschema] + eschema.ancestors()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   171
        # browse ancestors from most specific to most generic and
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   172
        # try to find an associated custom entity class
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   173
        for baseschema in baseschemas:
1923
3802c2e37e72 handle speaking to an instance using old entity types
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1917
diff changeset
   174
            try:
3802c2e37e72 handle speaking to an instance using old entity types
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1917
diff changeset
   175
                btype = ETYPE_NAME_MAP[baseschema]
3802c2e37e72 handle speaking to an instance using old entity types
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1917
diff changeset
   176
            except KeyError:
3802c2e37e72 handle speaking to an instance using old entity types
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1917
diff changeset
   177
                btype = str(baseschema)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   178
            try:
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: 395
diff changeset
   179
                cls = self.select(self.registry_objects('etypes', btype), etype)
99f5852f8604 major selector refactoring (mostly to avoid looking for select parameters on the target class), start accept / interface unification)
sylvain.thenault@logilab.fr
parents: 395
diff changeset
   180
                break
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   181
            except ObjectNotFound:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   182
                pass
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: 395
diff changeset
   183
        else:
99f5852f8604 major selector refactoring (mostly to avoid looking for select parameters on the target class), start accept / interface unification)
sylvain.thenault@logilab.fr
parents: 395
diff changeset
   184
            # no entity class for any of the ancestors, fallback to the default
99f5852f8604 major selector refactoring (mostly to avoid looking for select parameters on the target class), start accept / interface unification)
sylvain.thenault@logilab.fr
parents: 395
diff changeset
   185
            # one
99f5852f8604 major selector refactoring (mostly to avoid looking for select parameters on the target class), start accept / interface unification)
sylvain.thenault@logilab.fr
parents: 395
diff changeset
   186
            cls = self.select(self.registry_objects('etypes', 'Any'), etype)
99f5852f8604 major selector refactoring (mostly to avoid looking for select parameters on the target class), start accept / interface unification)
sylvain.thenault@logilab.fr
parents: 395
diff changeset
   187
        return cls
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   188
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   189
    def render(self, registry, oid, req, **context):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   190
        """select an object in a given registry and render it
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   191
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   192
        - registry: the registry's name
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   193
        - oid : the view to call
1475
5c1ec97f317e should not be necessary anymore to add entity class to __implements__
sylvain.thenault@logilab.fr
parents: 1357
diff changeset
   194
        - req : the HTTP request
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   195
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   196
        objclss = self.registry_objects(registry, oid)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   197
        try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   198
            rset = context.pop('rset')
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   199
        except KeyError:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   200
            rset = None
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   201
        selected = self.select(objclss, req, rset, **context)
1723
30c3a713ab61 View.dispatch -> View.render
sylvain.thenault@logilab.fr
parents: 1641
diff changeset
   202
        return selected.render(**context)
1475
5c1ec97f317e should not be necessary anymore to add entity class to __implements__
sylvain.thenault@logilab.fr
parents: 1357
diff changeset
   203
823
cb8ccbef8fa5 main template refactoring
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 816
diff changeset
   204
    def main_template(self, req, oid='main-template', **context):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   205
        """display query by calling the given template (default to main),
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   206
        and returning the output as a string instead of requiring the [w]rite
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   207
        method as argument
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   208
        """
816
9cd49a910fce kill Template class and 'templates' registry
sylvain.thenault@logilab.fr
parents: 785
diff changeset
   209
        res = self.render('views', oid, req, **context)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   210
        if isinstance(res, unicode):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   211
            return res.encode(req.encoding)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   212
        assert isinstance(res, str)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   213
        return res
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   214
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   215
    def possible_vobjects(self, registry, *args, **kwargs):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   216
        """return an ordered list of possible app objects in a given registry,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   217
        supposing they support the 'visible' and 'order' properties (as most
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   218
        visualizable objects)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   219
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   220
        return [x for x in sorted(self.possible_objects(registry, *args, **kwargs),
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   221
                                  key=lambda x: x.propval('order'))
213
6842c3dee34b adding files (formely appearing in jpl) specific to cubicweb
Laure Bourgois <Laure.Bourgois@logilab.fr>
parents: 169
diff changeset
   222
                if x.propval('visible')]
1475
5c1ec97f317e should not be necessary anymore to add entity class to __implements__
sylvain.thenault@logilab.fr
parents: 1357
diff changeset
   223
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   224
    def possible_actions(self, req, rset, **kwargs):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   225
        if rset is None:
1381
6042f1b342bb consider kwargs in possible_actions
sylvain.thenault@logilab.fr
parents: 1254
diff changeset
   226
            actions = self.possible_vobjects('actions', req, rset, **kwargs)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   227
        else:
1381
6042f1b342bb consider kwargs in possible_actions
sylvain.thenault@logilab.fr
parents: 1254
diff changeset
   228
            actions = rset.possible_actions(**kwargs) # cached implementation
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   229
        result = {}
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   230
        for action in actions:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   231
            result.setdefault(action.category, []).append(action)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   232
        return result
1475
5c1ec97f317e should not be necessary anymore to add entity class to __implements__
sylvain.thenault@logilab.fr
parents: 1357
diff changeset
   233
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   234
    def possible_views(self, req, rset, **kwargs):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   235
        """return an iterator on possible views for this result set
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   236
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   237
        views returned are classes, not instances
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   238
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   239
        for vid, views in self.registry('views').items():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   240
            if vid[0] == '_':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   241
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   242
            try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   243
                view = self.select(views, req, rset, **kwargs)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   244
                if view.linkable():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   245
                    yield view
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   246
            except NoSelectableObject:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   247
                continue
395
cce260264122 catch Exception in case there is some unexepected selector bug
sylvain.thenault@logilab.fr
parents: 355
diff changeset
   248
            except Exception:
cce260264122 catch Exception in case there is some unexepected selector bug
sylvain.thenault@logilab.fr
parents: 355
diff changeset
   249
                self.exception('error while trying to list possible %s views for %s',
cce260264122 catch Exception in case there is some unexepected selector bug
sylvain.thenault@logilab.fr
parents: 355
diff changeset
   250
                               vid, rset)
1475
5c1ec97f317e should not be necessary anymore to add entity class to __implements__
sylvain.thenault@logilab.fr
parents: 1357
diff changeset
   251
1985
9c1db4e06095 move view method's logic on the registry, so it's easier to call it from outside an appobject. Also make rset argument optional
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   252
    def view(self, __vid, req, rset=None, __fallback_vid=None, **kwargs):
9c1db4e06095 move view method's logic on the registry, so it's easier to call it from outside an appobject. Also make rset argument optional
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   253
        """shortcut to self.vreg.render method avoiding to pass self.req"""
9c1db4e06095 move view method's logic on the registry, so it's easier to call it from outside an appobject. Also make rset argument optional
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   254
        try:
9c1db4e06095 move view method's logic on the registry, so it's easier to call it from outside an appobject. Also make rset argument optional
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   255
            view = self.select_view(__vid, req, rset, **kwargs)
9c1db4e06095 move view method's logic on the registry, so it's easier to call it from outside an appobject. Also make rset argument optional
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   256
        except NoSelectableObject:
9c1db4e06095 move view method's logic on the registry, so it's easier to call it from outside an appobject. Also make rset argument optional
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   257
            if __fallback_vid is None:
9c1db4e06095 move view method's logic on the registry, so it's easier to call it from outside an appobject. Also make rset argument optional
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   258
                raise
9c1db4e06095 move view method's logic on the registry, so it's easier to call it from outside an appobject. Also make rset argument optional
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   259
            view = self.select_view(__fallback_vid, req, rset, **kwargs)
9c1db4e06095 move view method's logic on the registry, so it's easier to call it from outside an appobject. Also make rset argument optional
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   260
        return view.render(**kwargs)
9c1db4e06095 move view method's logic on the registry, so it's easier to call it from outside an appobject. Also make rset argument optional
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   261
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   262
    def select_box(self, oid, *args, **kwargs):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   263
        """return the most specific view according to the result set"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   264
        try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   265
            return self.select_object('boxes', oid, *args, **kwargs)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   266
        except NoSelectableObject:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   267
            return
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   268
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   269
    def select_action(self, oid, *args, **kwargs):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   270
        """return the most specific view according to the result set"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   271
        try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   272
            return self.select_object('actions', oid, *args, **kwargs)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   273
        except NoSelectableObject:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   274
            return
1475
5c1ec97f317e should not be necessary anymore to add entity class to __implements__
sylvain.thenault@logilab.fr
parents: 1357
diff changeset
   275
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   276
    def select_component(self, cid, *args, **kwargs):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   277
        """return the most specific component according to the result set"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   278
        try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   279
            return self.select_object('components', cid, *args, **kwargs)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   280
        except (NoSelectableObject, ObjectNotFound):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   281
            return
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   282
1985
9c1db4e06095 move view method's logic on the registry, so it's easier to call it from outside an appobject. Also make rset argument optional
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   283
    def select_view(self, __vid, req, rset=None, **kwargs):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   284
        """return the most specific view according to the result set"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   285
        views = self.registry_objects('views', __vid)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   286
        return self.select(views, req, rset, **kwargs)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   287
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   288
    # properties handling #####################################################
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   289
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   290
    def user_property_keys(self, withsitewide=False):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   291
        if withsitewide:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   292
            return sorted(self['propertydefs'])
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   293
        return sorted(k for k, kd in self['propertydefs'].iteritems()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   294
                      if not kd['sitewide'])
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   295
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   296
    def register_property(self, key, type, help, default=None, vocabulary=None,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   297
                          sitewide=False):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   298
        """register a given property"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   299
        properties = self._registries['propertydefs']
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   300
        assert type in YAMS_TO_PY
1475
5c1ec97f317e should not be necessary anymore to add entity class to __implements__
sylvain.thenault@logilab.fr
parents: 1357
diff changeset
   301
        properties[key] = {'type': type, 'vocabulary': vocabulary,
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   302
                           'default': default, 'help': help,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   303
                           'sitewide': sitewide}
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   304
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   305
    def property_info(self, key):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   306
        """return dictionary containing description associated to the given
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   307
        property key (including type, defaut value, help and a site wide
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   308
        boolean)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   309
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   310
        try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   311
            return self._registries['propertydefs'][key]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   312
        except KeyError:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   313
            if key.startswith('system.version.'):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   314
                soft = key.split('.')[-1]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   315
                return {'type': 'String', 'sitewide': True,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   316
                        'default': None, 'vocabulary': None,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   317
                        'help': _('%s software version of the database') % soft}
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   318
            raise UnknownProperty('unregistered property %r' % key)
1475
5c1ec97f317e should not be necessary anymore to add entity class to __implements__
sylvain.thenault@logilab.fr
parents: 1357
diff changeset
   319
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   320
    def property_value(self, key):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   321
        try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   322
            return self._registries['propertyvalues'][key]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   323
        except KeyError:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   324
            return self._registries['propertydefs'][key]['default']
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   325
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   326
    def typed_value(self, key, value):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   327
        """value is an unicode string, return it correctly typed. Let potential
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   328
        type error propagates.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   329
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   330
        pdef = self.property_info(key)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   331
        try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   332
            value = YAMS_TO_PY[pdef['type']](value)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   333
        except (TypeError, ValueError):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   334
            raise ValueError(_('bad value'))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   335
        vocab = pdef['vocabulary']
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   336
        if vocab is not None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   337
            if callable(vocab):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   338
                vocab = vocab(key, None) # XXX need a req object
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   339
            if not value in vocab:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   340
                raise ValueError(_('unauthorized value'))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   341
        return value
1475
5c1ec97f317e should not be necessary anymore to add entity class to __implements__
sylvain.thenault@logilab.fr
parents: 1357
diff changeset
   342
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   343
    def init_properties(self, propvalues):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   344
        """init the property values registry using the given set of couple (key, value)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   345
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   346
        self.initialized = True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   347
        values = self._registries['propertyvalues']
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   348
        for key, val in propvalues:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   349
            try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   350
                values[key] = self.typed_value(key, val)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   351
            except ValueError:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   352
                self.warning('%s (you should probably delete that property '
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   353
                             'from the database)', ex)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   354
            except UnknownProperty, ex:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   355
                self.warning('%s (you should probably delete that property '
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   356
                             'from the database)', ex)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   357
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   358
    def parse(self, session, rql, args=None):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   359
        rqlst = self.rqlhelper.parse(rql)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   360
        def type_from_eid(eid, session=session):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   361
            return session.describe(eid)[0]
1123
a8e2838f174a catch UnknownEid and set empty solutions on select nodes
sylvain.thenault@logilab.fr
parents: 395
diff changeset
   362
        try:
a8e2838f174a catch UnknownEid and set empty solutions on select nodes
sylvain.thenault@logilab.fr
parents: 395
diff changeset
   363
            self.rqlhelper.compute_solutions(rqlst, {'eid': type_from_eid}, args)
a8e2838f174a catch UnknownEid and set empty solutions on select nodes
sylvain.thenault@logilab.fr
parents: 395
diff changeset
   364
        except UnknownEid:
a8e2838f174a catch UnknownEid and set empty solutions on select nodes
sylvain.thenault@logilab.fr
parents: 395
diff changeset
   365
            for select in rqlst.children:
a8e2838f174a catch UnknownEid and set empty solutions on select nodes
sylvain.thenault@logilab.fr
parents: 395
diff changeset
   366
                select.solutions = []
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   367
        return rqlst
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   368
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   369
    @property
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   370
    @cached
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   371
    def rqlhelper(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   372
        return RQLHelper(self.schema,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   373
                         special_relations={'eid': 'uid', 'has_text': 'fti'})
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   374
169
0e031b66cb0b don't systematically init_log, it may breaks client log configuration
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 0
diff changeset
   375
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   376
class MulCnxCubicWebRegistry(CubicWebRegistry):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   377
    """special registry to be used when an application has to deal with
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   378
    connections to differents repository. This class add some additional wrapper
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   379
    trying to hide buggy class attributes since classes are not designed to be
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   380
    shared.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   381
    """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   382
    def etype_class(self, etype):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   383
        """return an entity class for the given entity type.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   384
        Try to find out a specific class for this kind of entity or
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   385
        default to a dump of the class registered for 'Any'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   386
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   387
        usercls = super(MulCnxCubicWebRegistry, self).etype_class(etype)
1917
eaf6e0edc509 fix etype_class(Any) when multiple sources
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 1769
diff changeset
   388
        if etype == 'Any':
eaf6e0edc509 fix etype_class(Any) when multiple sources
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 1769
diff changeset
   389
            return usercls
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   390
        usercls.e_schema = self.schema.eschema(etype)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   391
        return usercls
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   392
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   393
    def select(self, vobjects, *args, **kwargs):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   394
        """return an instance of the most specific object according
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   395
        to parameters
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   396
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   397
        raise NoSelectableObject if not object apply
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   398
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   399
        for vobject in vobjects:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   400
            vobject.vreg = self
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   401
            vobject.schema = self.schema
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   402
            vobject.config = self.config
1923
3802c2e37e72 handle speaking to an instance using old entity types
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1917
diff changeset
   403
        selected = super(MulCnxCubicWebRegistry, self).select(vobjects, *args,
3802c2e37e72 handle speaking to an instance using old entity types
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1917
diff changeset
   404
                                                              **kwargs)
3802c2e37e72 handle speaking to an instance using old entity types
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1917
diff changeset
   405
        # redo the same thing on the instance so it won't use equivalent class
3802c2e37e72 handle speaking to an instance using old entity types
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1917
diff changeset
   406
        # attributes (which may change)
3802c2e37e72 handle speaking to an instance using old entity types
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1917
diff changeset
   407
        selected.vreg = self
3802c2e37e72 handle speaking to an instance using old entity types
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1917
diff changeset
   408
        selected.schema = self.schema
3802c2e37e72 handle speaking to an instance using old entity types
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1917
diff changeset
   409
        selected.config = self.config
3802c2e37e72 handle speaking to an instance using old entity types
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1917
diff changeset
   410
        return selected
1475
5c1ec97f317e should not be necessary anymore to add entity class to __implements__
sylvain.thenault@logilab.fr
parents: 1357
diff changeset
   411
1016
26387b836099 use datetime instead of mx.DateTime
sylvain.thenault@logilab.fr
parents: 823
diff changeset
   412
from datetime import datetime, date, time, timedelta
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   413
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   414
YAMS_TO_PY = {
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   415
    'Boolean':  bool,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   416
    'String' :  unicode,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   417
    'Password': str,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   418
    'Bytes':    Binary,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   419
    'Int':      int,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   420
    'Float':    float,
1016
26387b836099 use datetime instead of mx.DateTime
sylvain.thenault@logilab.fr
parents: 823
diff changeset
   421
    'Date':     date,
26387b836099 use datetime instead of mx.DateTime
sylvain.thenault@logilab.fr
parents: 823
diff changeset
   422
    'Datetime': datetime,
26387b836099 use datetime instead of mx.DateTime
sylvain.thenault@logilab.fr
parents: 823
diff changeset
   423
    'Time':     time,
26387b836099 use datetime instead of mx.DateTime
sylvain.thenault@logilab.fr
parents: 823
diff changeset
   424
    'Interval': timedelta,
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   425
    }
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   426