schema.py
author Sylvain Thénault <sylvain.thenault@logilab.fr>
Wed, 09 Dec 2009 09:52:28 +0100
changeset 4066 0555f170c4d1
parent 4045 f4a52abb6f4f
child 4151 66fe38345a65
permissions -rw-r--r--
__cmp__ should *NOT* return False when different
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     1
"""classes to define schemas for CubicWeb
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: 1498
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: 1498
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"
2142
098aa2075903 include_schema_files is useless
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
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
import re
2147
476a75ede2cc merge and add missing import in schema.py
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2142
diff changeset
    12
from os.path import join
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    13
from logging import getLogger
1133
8a409ea0c9ec more linting
sylvain.thenault@logilab.fr
parents: 1132
diff changeset
    14
from warnings import warn
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    15
624
258e5692ae06 provide a new RichString attribute type
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 479
diff changeset
    16
from logilab.common.decorators import cached, clear_cache, monkeypatch
2730
bb6fcb8c5d71 to make cw schemas importable, they have to be installed w/ cw code, not in /usr/share/cubicweb/schemas
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2718
diff changeset
    17
from logilab.common.logging_ext import set_log_methods
2613
5e19c2bb370e R [all] logilab.common 0.44 provides only deprecated
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2531
diff changeset
    18
from logilab.common.deprecation import deprecated
2926
4484387ed012 when adding/removing cubes, we should add/remove entity types in correct order if one inherits from another
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
    19
from logilab.common.graph import get_cycles
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    20
from logilab.common.compat import any
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    21
2531
531ea4e7013e [cleanup] nicer imports
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2526
diff changeset
    22
from yams import BadSchemaDefinition, buildobjs as ybo
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
    23
from yams.schema import Schema, ERSchema, EntitySchema, RelationSchema, \
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
    24
     RelationDefinitionSchema, PermissionMixIn
2531
531ea4e7013e [cleanup] nicer imports
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2526
diff changeset
    25
from yams.constraints import (BaseConstraint, StaticVocabularyConstraint,
531ea4e7013e [cleanup] nicer imports
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2526
diff changeset
    26
                              FormatConstraint)
531ea4e7013e [cleanup] nicer imports
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2526
diff changeset
    27
from yams.reader import (CONSTRAINTS, PyFileReader, SchemaLoader,
531ea4e7013e [cleanup] nicer imports
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2526
diff changeset
    28
                         obsolete as yobsolete, cleanup_sys_modules)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    29
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    30
from rql import parse, nodes, RQLSyntaxError, TypeResolverException
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    31
2730
bb6fcb8c5d71 to make cw schemas importable, they have to be installed w/ cw code, not in /usr/share/cubicweb/schemas
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2718
diff changeset
    32
import cubicweb
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    33
from cubicweb import ETYPE_NAME_MAP, ValidationError, Unauthorized
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    34
1016
26387b836099 use datetime instead of mx.DateTime
sylvain.thenault@logilab.fr
parents: 745
diff changeset
    35
# XXX <3.2 bw compat
26387b836099 use datetime instead of mx.DateTime
sylvain.thenault@logilab.fr
parents: 745
diff changeset
    36
from yams import schema
26387b836099 use datetime instead of mx.DateTime
sylvain.thenault@logilab.fr
parents: 745
diff changeset
    37
schema.use_py_datetime()
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
    38
nodes.use_py_datetime()
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    39
2596
d02eed70937f [R repo, schema] use VIRTUAL_RTYPES const
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2531
diff changeset
    40
PURE_VIRTUAL_RTYPES = set(('identity', 'has_text',))
d02eed70937f [R repo, schema] use VIRTUAL_RTYPES const
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2531
diff changeset
    41
VIRTUAL_RTYPES = set(('eid', 'identity', 'has_text',))
d02eed70937f [R repo, schema] use VIRTUAL_RTYPES const
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2531
diff changeset
    42
2126
a25859917ccc stop using meta attribute from yams schema. Use instead sets defining meta relations and another defining schema types. Refactor various schema view based on this
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
    43
#  set of meta-relations available for every entity types
2622
3c7edaa6c6d2 oops, should have been in a earlier commit (META_RELATION_TYPES renaming)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2616
diff changeset
    44
META_RTYPES = set((
2126
a25859917ccc stop using meta attribute from yams schema. Use instead sets defining meta relations and another defining schema types. Refactor various schema view based on this
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
    45
    'owned_by', 'created_by', 'is', 'is_instance_of', 'identity',
2456
aa25d6b244c8 new cwuri metadata + a few tests fixes on the way
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2437
diff changeset
    46
    'eid', 'creation_date', 'modification_date', 'has_text', 'cwuri',
2184
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2181
diff changeset
    47
    ))
3287
19c1011736a6 tweak catalog generation by adding a new SYSTEM_RTYPES set to schema
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3284
diff changeset
    48
SYSTEM_RTYPES = set(('require_permission', 'custom_workflow', 'in_state', 'wf_info_for'))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    49
2126
a25859917ccc stop using meta attribute from yams schema. Use instead sets defining meta relations and another defining schema types. Refactor various schema view based on this
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
    50
#  set of entity and relation types used to build the schema
a25859917ccc stop using meta attribute from yams schema. Use instead sets defining meta relations and another defining schema types. Refactor various schema view based on this
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
    51
SCHEMA_TYPES = set((
a25859917ccc stop using meta attribute from yams schema. Use instead sets defining meta relations and another defining schema types. Refactor various schema view based on this
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
    52
    'CWEType', 'CWRType', 'CWAttribute', 'CWRelation',
a25859917ccc stop using meta attribute from yams schema. Use instead sets defining meta relations and another defining schema types. Refactor various schema view based on this
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
    53
    'CWConstraint', 'CWConstraintType', 'RQLExpression',
a25859917ccc stop using meta attribute from yams schema. Use instead sets defining meta relations and another defining schema types. Refactor various schema view based on this
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
    54
    'relation_type', 'from_entity', 'to_entity',
a25859917ccc stop using meta attribute from yams schema. Use instead sets defining meta relations and another defining schema types. Refactor various schema view based on this
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
    55
    'constrained_by', 'cstrtype',
a25859917ccc stop using meta attribute from yams schema. Use instead sets defining meta relations and another defining schema types. Refactor various schema view based on this
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
    56
    ))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    57
2142
098aa2075903 include_schema_files is useless
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
    58
_LOGGER = getLogger('cubicweb.schemaloader')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    59
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    60
# schema entities created from serialized schema have an eid rproperty
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    61
ybo.ETYPE_PROPERTIES += ('eid',)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    62
ybo.RTYPE_PROPERTIES += ('eid',)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    63
ybo.RDEF_PROPERTIES += ('eid',)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    64
2926
4484387ed012 when adding/removing cubes, we should add/remove entity types in correct order if one inherits from another
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
    65
4484387ed012 when adding/removing cubes, we should add/remove entity types in correct order if one inherits from another
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
    66
# XXX same algorithm as in reorder_cubes and probably other place,
4484387ed012 when adding/removing cubes, we should add/remove entity types in correct order if one inherits from another
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
    67
# may probably extract a generic function
4484387ed012 when adding/removing cubes, we should add/remove entity types in correct order if one inherits from another
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
    68
def order_eschemas(eschemas):
4484387ed012 when adding/removing cubes, we should add/remove entity types in correct order if one inherits from another
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
    69
    """return entity schemas ordered such that entity types which specializes an
4484387ed012 when adding/removing cubes, we should add/remove entity types in correct order if one inherits from another
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
    70
    other one appears after that one
4484387ed012 when adding/removing cubes, we should add/remove entity types in correct order if one inherits from another
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
    71
    """
4484387ed012 when adding/removing cubes, we should add/remove entity types in correct order if one inherits from another
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
    72
    graph = {}
4484387ed012 when adding/removing cubes, we should add/remove entity types in correct order if one inherits from another
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
    73
    for eschema in eschemas:
4484387ed012 when adding/removing cubes, we should add/remove entity types in correct order if one inherits from another
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
    74
        if eschema.specializes():
4484387ed012 when adding/removing cubes, we should add/remove entity types in correct order if one inherits from another
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
    75
            graph[eschema] = set((eschema.specializes(),))
4484387ed012 when adding/removing cubes, we should add/remove entity types in correct order if one inherits from another
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
    76
        else:
4484387ed012 when adding/removing cubes, we should add/remove entity types in correct order if one inherits from another
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
    77
            graph[eschema] = set()
4484387ed012 when adding/removing cubes, we should add/remove entity types in correct order if one inherits from another
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
    78
    cycles = get_cycles(graph)
4484387ed012 when adding/removing cubes, we should add/remove entity types in correct order if one inherits from another
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
    79
    if cycles:
4484387ed012 when adding/removing cubes, we should add/remove entity types in correct order if one inherits from another
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
    80
        cycles = '\n'.join(' -> '.join(cycle) for cycle in cycles)
4484387ed012 when adding/removing cubes, we should add/remove entity types in correct order if one inherits from another
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
    81
        raise Exception('cycles in entity schema specialization: %s'
4484387ed012 when adding/removing cubes, we should add/remove entity types in correct order if one inherits from another
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
    82
                        % cycles)
4484387ed012 when adding/removing cubes, we should add/remove entity types in correct order if one inherits from another
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
    83
    eschemas = []
4484387ed012 when adding/removing cubes, we should add/remove entity types in correct order if one inherits from another
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
    84
    while graph:
4484387ed012 when adding/removing cubes, we should add/remove entity types in correct order if one inherits from another
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
    85
        # sorted to get predictable results
4484387ed012 when adding/removing cubes, we should add/remove entity types in correct order if one inherits from another
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
    86
        for eschema, deps in sorted(graph.items()):
4484387ed012 when adding/removing cubes, we should add/remove entity types in correct order if one inherits from another
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
    87
            if not deps:
4484387ed012 when adding/removing cubes, we should add/remove entity types in correct order if one inherits from another
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
    88
                eschemas.append(eschema)
4484387ed012 when adding/removing cubes, we should add/remove entity types in correct order if one inherits from another
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
    89
                del graph[eschema]
4484387ed012 when adding/removing cubes, we should add/remove entity types in correct order if one inherits from another
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
    90
                for deps in graph.itervalues():
4484387ed012 when adding/removing cubes, we should add/remove entity types in correct order if one inherits from another
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
    91
                    try:
4484387ed012 when adding/removing cubes, we should add/remove entity types in correct order if one inherits from another
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
    92
                        deps.remove(eschema)
4484387ed012 when adding/removing cubes, we should add/remove entity types in correct order if one inherits from another
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
    93
                    except KeyError:
4484387ed012 when adding/removing cubes, we should add/remove entity types in correct order if one inherits from another
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
    94
                        continue
4484387ed012 when adding/removing cubes, we should add/remove entity types in correct order if one inherits from another
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
    95
    return eschemas
4484387ed012 when adding/removing cubes, we should add/remove entity types in correct order if one inherits from another
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
    96
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    97
def bw_normalize_etype(etype):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    98
    if etype in ETYPE_NAME_MAP:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    99
        msg = '%s has been renamed to %s, please update your code' % (
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   100
            etype, ETYPE_NAME_MAP[etype])
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   101
        warn(msg, DeprecationWarning, stacklevel=4)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   102
        etype = ETYPE_NAME_MAP[etype]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   103
    return etype
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   104
3275
5247789df541 [gettext] provide GNU contexts to avoid translations ambiguities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3240
diff changeset
   105
def display_name(req, key, form='', context=None):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   106
    """return a internationalized string for the key (schema entity or relation
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   107
    name) in a given form
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   108
    """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   109
    assert form in ('', 'plural', 'subject', 'object')
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   110
    if form == 'subject':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   111
        form = ''
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   112
    if form:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   113
        key = key + '_' + form
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   114
    # ensure unicode
3284
036cf5a25714 ensure pgettext return unicode as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3275
diff changeset
   115
    # .lower() in case no translation are available XXX done whatever a translation is there or not!
036cf5a25714 ensure pgettext return unicode as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3275
diff changeset
   116
    if context is not None:
036cf5a25714 ensure pgettext return unicode as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3275
diff changeset
   117
        return unicode(req.pgettext(context, key)).lower()
3275
5247789df541 [gettext] provide GNU contexts to avoid translations ambiguities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3240
diff changeset
   118
    else:
5247789df541 [gettext] provide GNU contexts to avoid translations ambiguities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3240
diff changeset
   119
        return unicode(req._(key)).lower()
5247789df541 [gettext] provide GNU contexts to avoid translations ambiguities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3240
diff changeset
   120
2788
8d3dbe577d3a R put version info in deprecation warnings
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2782
diff changeset
   121
__builtins__['display_name'] = deprecated('[3.4] display_name should be imported from cubicweb.schema')(display_name)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   122
3978
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   123
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   124
# rql expression utilities function ############################################
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   125
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   126
def guess_rrqlexpr_mainvars(expression):
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   127
    defined = set(split_expression(expression))
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   128
    mainvars = []
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   129
    if 'S' in defined:
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   130
        mainvars.append('S')
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   131
    if 'O' in defined:
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   132
        mainvars.append('O')
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   133
    if 'U' in defined:
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   134
        mainvars.append('U')
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   135
    if not mainvars:
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   136
        raise Exception('unable to guess selection variables')
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   137
    return ','.join(mainvars)
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   138
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   139
def split_expression(rqlstring):
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   140
    for expr in rqlstring.split(','):
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   141
        for word in expr.split():
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   142
            yield word
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   143
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   144
def normalize_expression(rqlstring):
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   145
    """normalize an rql expression to ease schema synchronization (avoid
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   146
    suppressing and reinserting an expression if only a space has been added/removed
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   147
    for instance)
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   148
    """
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   149
    return u', '.join(' '.join(expr.split()) for expr in rqlstring.split(','))
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   150
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   151
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   152
# Schema objects definition ###################################################
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   153
3471
8c57c71b859c can now give context to rschema.display_name(...)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3401
diff changeset
   154
def ERSchema_display_name(self, req, form='', context=None):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   155
    """return a internationalized string for the entity/relation type name in
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   156
    a given form
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   157
    """
3471
8c57c71b859c can now give context to rschema.display_name(...)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3401
diff changeset
   158
    return display_name(req, self.type, form, context)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   159
ERSchema.display_name = ERSchema_display_name
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   160
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   161
@cached
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   162
def get_groups(self, action):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   163
    """return the groups authorized to perform <action> on entities of
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   164
    this type
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
    :type action: str
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   167
    :param action: the name of a permission
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   168
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   169
    :rtype: tuple
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   170
    :return: names of the groups with the given permission
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
    assert action in self.ACTIONS, action
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   173
    #assert action in self._groups, '%s %s' % (self, action)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   174
    try:
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   175
        return frozenset(g for g in self.permissions[action] if isinstance(g, basestring))
0
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
        return ()
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   178
PermissionMixIn.get_groups = get_groups
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   179
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   180
@cached
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   181
def get_rqlexprs(self, action):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   182
    """return the rql expressions representing queries to check the user is allowed
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   183
    to perform <action> on entities of this type
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   184
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   185
    :type action: str
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   186
    :param action: the name of a permission
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   187
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   188
    :rtype: tuple
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   189
    :return: the rql expressions with the given permission
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   190
    """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   191
    assert action in self.ACTIONS, action
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   192
    #assert action in self._rqlexprs, '%s %s' % (self, action)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   193
    try:
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   194
        return tuple(g for g in self.permissions[action] if not isinstance(g, basestring))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   195
    except KeyError:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   196
        return ()
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   197
PermissionMixIn.get_rqlexprs = get_rqlexprs
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   198
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   199
orig_set_action_permissions = PermissionMixIn.set_action_permissions
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   200
def set_action_permissions(self, action, permissions):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   201
    """set the groups and rql expressions allowing to perform <action> on
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   202
    entities of this type
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   203
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   204
    :type action: str
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   205
    :param action: the name of a permission
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   206
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   207
    :type permissions: tuple
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   208
    :param permissions: the groups and rql expressions allowing the given action
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   209
    """
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   210
    orig_set_action_permissions(self, action, tuple(permissions))
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   211
    clear_cache(self, 'get_rqlexprs')
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   212
    clear_cache(self, 'get_groups')
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   213
PermissionMixIn.set_action_permissions = set_action_permissions
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   214
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   215
def has_local_role(self, action):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   216
    """return true if the action *may* be granted localy (eg either rql
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   217
    expressions or the owners group are used in security definition)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   218
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   219
    XXX this method is only there since we don't know well how to deal with
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   220
    'add' action checking. Also find a better name would be nice.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   221
    """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   222
    assert action in self.ACTIONS, action
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   223
    if self.get_rqlexprs(action):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   224
        return True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   225
    if action in ('update', 'delete'):
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   226
        return 'owners' in self.get_groups(action)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   227
    return False
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   228
PermissionMixIn.has_local_role = has_local_role
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   229
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   230
def may_have_permission(self, action, req):
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   231
    if action != 'read' and not (self.has_local_role('read') or
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   232
                                 self.has_perm(req, 'read')):
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   233
        return False
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   234
    return self.has_local_role(action) or self.has_perm(req, action)
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   235
PermissionMixIn.may_have_permission = may_have_permission
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   236
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   237
def has_perm(self, session, action, **kwargs):
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   238
    """return true if the action is granted globaly or localy"""
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   239
    try:
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   240
        self.check_perm(session, action, **kwargs)
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   241
        return True
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   242
    except Unauthorized:
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   243
        return False
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   244
PermissionMixIn.has_perm = has_perm
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   245
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   246
def check_perm(self, session, action, **kwargs):
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   247
    # NB: session may be a server session or a request object check user is
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   248
    # in an allowed group, if so that's enough internal sessions should
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   249
    # always stop there
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   250
    groups = self.get_groups(action)
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   251
    if session.user.matching_groups(groups):
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   252
        return
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   253
    # if 'owners' in allowed groups, check if the user actually owns this
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   254
    # object, if so that's enough
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   255
    if 'owners' in groups and 'eid' in kwargs and session.user.owns(kwargs['eid']):
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   256
        return
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   257
    # else if there is some rql expressions, check them
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   258
    if any(rqlexpr.check(session, **kwargs)
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   259
           for rqlexpr in self.get_rqlexprs(action)):
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   260
        return
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   261
    raise Unauthorized(action, str(self))
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   262
PermissionMixIn.check_perm = check_perm
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   263
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   264
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   265
RelationDefinitionSchema._RPROPERTIES['eid'] = None
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   266
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   267
def rql_expression(self, expression, mainvars=None, eid=None):
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   268
    """rql expression factory"""
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   269
    if self.rtype.final:
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   270
        return ERQLExpression(expression, mainvars, eid)
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   271
    return RRQLExpression(expression, mainvars, eid)
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   272
RelationDefinitionSchema.rql_expression = rql_expression
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   273
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   274
orig_check_permission_definitions = RelationDefinitionSchema.check_permission_definitions
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   275
def check_permission_definitions(self):
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   276
    orig_check_permission_definitions(self)
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   277
    schema = self.subject.schema
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   278
    for action, groups in self.permissions.iteritems():
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   279
        for group_or_rqlexpr in groups:
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   280
            if action == 'read' and \
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   281
                   isinstance(group_or_rqlexpr, RQLExpression):
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   282
                msg = "can't use rql expression for read permission of %s"
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   283
                raise BadSchemaDefinition(msg % self)
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   284
            elif self.final and isinstance(group_or_rqlexpr, RRQLExpression):
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   285
                if schema.reading_from_database:
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   286
                    # we didn't have final relation earlier, so turn
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   287
                    # RRQLExpression into ERQLExpression now
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   288
                    rqlexpr = group_or_rqlexpr
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   289
                    newrqlexprs = [x for x in self.get_rqlexprs(action)
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   290
                                   if not x is rqlexpr]
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   291
                    newrqlexprs.append(ERQLExpression(rqlexpr.expression,
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   292
                                                      rqlexpr.mainvars,
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   293
                                                      rqlexpr.eid))
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   294
                    self.set_rqlexprs(action, newrqlexprs)
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   295
                else:
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   296
                    msg = "can't use RRQLExpression on %s, use an ERQLExpression"
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   297
                    raise BadSchemaDefinition(msg % self)
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   298
            elif not self.final and \
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   299
                     isinstance(group_or_rqlexpr, ERQLExpression):
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   300
                msg = "can't use ERQLExpression on %s, use a RRQLExpression"
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   301
                raise BadSchemaDefinition(msg % self)
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   302
RelationDefinitionSchema.check_permission_definitions = check_permission_definitions
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   303
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
class CubicWebEntitySchema(EntitySchema):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   306
    """a entity has a type, a set of subject and or object relations
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   307
    the entity schema defines the possible relations for a given type and some
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   308
    constraints on those relations
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
    def __init__(self, schema=None, edef=None, eid=None, **kwargs):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   311
        super(CubicWebEntitySchema, self).__init__(schema, edef, **kwargs)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   312
        if eid is None and edef is not None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   313
            eid = getattr(edef, 'eid', None)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   314
        self.eid = eid
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   315
        # take care: no _groups attribute when deep-copying
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   316
        if getattr(self, 'permissions', None):
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   317
            for groups in self.permissions.itervalues():
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   318
                for group_or_rqlexpr in groups:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   319
                    if isinstance(group_or_rqlexpr, RRQLExpression):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   320
                        msg = "can't use RRQLExpression on an entity type, use an ERQLExpression (%s)"
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   321
                        raise BadSchemaDefinition(msg % self.type)
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   322
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   323
    def attribute_definitions(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   324
        """return an iterator on attribute definitions
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   325
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   326
        attribute relations are a subset of subject relations where the
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   327
        object's type is a final entity
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   328
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   329
        an attribute definition is a 2-uple :
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   330
        * name of the relation
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   331
        * schema of the destination entity type
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   332
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   333
        iter = super(CubicWebEntitySchema, self).attribute_definitions()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   334
        for rschema, attrschema in iter:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   335
            if rschema.type == 'has_text':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   336
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   337
            yield rschema, attrschema
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   338
2128
464edb198faa drop @ wildcard in relation subject/object, override main_attribute for proper behaviour
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2126
diff changeset
   339
    def main_attribute(self):
464edb198faa drop @ wildcard in relation subject/object, override main_attribute for proper behaviour
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2126
diff changeset
   340
        """convenience method that returns the *main* (i.e. the first non meta)
464edb198faa drop @ wildcard in relation subject/object, override main_attribute for proper behaviour
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2126
diff changeset
   341
        attribute defined in the entity schema
464edb198faa drop @ wildcard in relation subject/object, override main_attribute for proper behaviour
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2126
diff changeset
   342
        """
464edb198faa drop @ wildcard in relation subject/object, override main_attribute for proper behaviour
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2126
diff changeset
   343
        for rschema, _ in self.attribute_definitions():
2622
3c7edaa6c6d2 oops, should have been in a earlier commit (META_RELATION_TYPES renaming)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2616
diff changeset
   344
            if not (rschema in META_RTYPES
2128
464edb198faa drop @ wildcard in relation subject/object, override main_attribute for proper behaviour
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2126
diff changeset
   345
                    or self.is_metadata(rschema)):
464edb198faa drop @ wildcard in relation subject/object, override main_attribute for proper behaviour
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2126
diff changeset
   346
                return rschema
464edb198faa drop @ wildcard in relation subject/object, override main_attribute for proper behaviour
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2126
diff changeset
   347
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   348
    def add_subject_relation(self, rschema):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   349
        """register the relation schema as possible subject relation"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   350
        super(CubicWebEntitySchema, self).add_subject_relation(rschema)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   351
        self._update_has_text()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   352
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   353
    def del_subject_relation(self, rtype):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   354
        super(CubicWebEntitySchema, self).del_subject_relation(rtype)
2632
920bfaff60a4 B [schema update] may remove has_text unexpectedly, give another argument to fix it
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2622
diff changeset
   355
        self._update_has_text(True)
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   356
2632
920bfaff60a4 B [schema update] may remove has_text unexpectedly, give another argument to fix it
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2622
diff changeset
   357
    def _update_has_text(self, deletion=False):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   358
        may_need_has_text, has_has_text = False, False
2632
920bfaff60a4 B [schema update] may remove has_text unexpectedly, give another argument to fix it
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2622
diff changeset
   359
        need_has_text = None
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   360
        for rschema in self.subject_relations():
3689
deb13e88e037 follow yams 0.25 api changes to improve performance
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3554
diff changeset
   361
            if rschema.final:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   362
                if rschema == 'has_text':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   363
                    has_has_text = True
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   364
                elif self.rdef(rschema).get('fulltextindexed'):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   365
                    may_need_has_text = True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   366
            elif rschema.fulltext_container:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   367
                if rschema.fulltext_container == 'subject':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   368
                    may_need_has_text = True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   369
                else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   370
                    need_has_text = False
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   371
        for rschema in self.object_relations():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   372
            if rschema.fulltext_container:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   373
                if rschema.fulltext_container == 'object':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   374
                    may_need_has_text = True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   375
                else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   376
                    need_has_text = False
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   377
        if need_has_text is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   378
            need_has_text = may_need_has_text
2632
920bfaff60a4 B [schema update] may remove has_text unexpectedly, give another argument to fix it
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2622
diff changeset
   379
        if need_has_text and not has_has_text and not deletion:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   380
            rdef = ybo.RelationDefinition(self.type, 'has_text', 'String')
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   381
            self.schema.add_relation_def(rdef)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   382
        elif not need_has_text and has_has_text:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   383
            self.schema.del_relation_def(self.type, 'has_text', 'String')
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   384
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   385
    def schema_entity(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   386
        """return True if this entity type is used to build the schema"""
2126
a25859917ccc stop using meta attribute from yams schema. Use instead sets defining meta relations and another defining schema types. Refactor various schema view based on this
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   387
        return self.type in SCHEMA_TYPES
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   388
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   389
    def rql_expression(self, expression, mainvars=None, eid=None):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   390
        """rql expression factory"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   391
        return ERQLExpression(expression, mainvars, eid)
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   392
2252
dd9758cb77e1 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2222
diff changeset
   393
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   394
class CubicWebRelationSchema(RelationSchema):
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   395
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   396
    def __init__(self, schema=None, rdef=None, eid=None, **kwargs):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   397
        if rdef is not None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   398
            # if this relation is inlined
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   399
            self.inlined = rdef.inlined
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   400
        super(CubicWebRelationSchema, self).__init__(schema, rdef, **kwargs)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   401
        if eid is None and rdef is not None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   402
            eid = getattr(rdef, 'eid', None)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   403
        self.eid = eid
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   404
2126
a25859917ccc stop using meta attribute from yams schema. Use instead sets defining meta relations and another defining schema types. Refactor various schema view based on this
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   405
    @property
a25859917ccc stop using meta attribute from yams schema. Use instead sets defining meta relations and another defining schema types. Refactor various schema view based on this
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   406
    def meta(self):
2622
3c7edaa6c6d2 oops, should have been in a earlier commit (META_RELATION_TYPES renaming)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2616
diff changeset
   407
        return self.type in META_RTYPES
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   408
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   409
    def schema_relation(self):
2126
a25859917ccc stop using meta attribute from yams schema. Use instead sets defining meta relations and another defining schema types. Refactor various schema view based on this
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   410
        """return True if this relation type is used to build the schema"""
a25859917ccc stop using meta attribute from yams schema. Use instead sets defining meta relations and another defining schema types. Refactor various schema view based on this
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   411
        return self.type in SCHEMA_TYPES
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   412
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   413
    def may_have_permission(self, action, req, eschema=None, role=None):
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   414
        if eschema is not None:
4019
7f68077d2c3b api update
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4005
diff changeset
   415
            for tschema in self.targets(eschema, role):
7f68077d2c3b api update
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4005
diff changeset
   416
                rdef = self.role_rdef(eschema, tschema, role)
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   417
                if rdef.may_have_permission(action, req):
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   418
                    return True
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   419
        else:
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   420
            for rdef in self.rdefs.itervalues():
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   421
                if rdef.may_have_permission(action, req):
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   422
                    return True
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   423
        return False
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   424
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   425
    def has_perm(self, session, action, **kwargs):
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   426
        """return true if the action is granted globaly or localy"""
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   427
        if 'fromeid' in kwargs:
4005
dee7af82beff should return item type not relation
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4004
diff changeset
   428
            subjtype = session.describe(kwargs['fromeid'])[0]
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   429
        else:
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   430
            subjtype = None
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   431
        if 'toeid' in kwargs:
4005
dee7af82beff should return item type not relation
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4004
diff changeset
   432
            objtype = session.describe(kwargs['toeid'])[0]
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   433
        else:
4037
42f3a80738d7 [mq]: typo
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4019
diff changeset
   434
            objtype = None
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   435
        if objtype and subjtype:
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   436
            return self.rdef(subjtype, objtype).has_perm(session, action, **kwargs)
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   437
        elif subjtype:
4004
c52619c738a5 api renaming update
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4003
diff changeset
   438
            for tschema in self.targets(subjtype, 'subject'):
c52619c738a5 api renaming update
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4003
diff changeset
   439
                rdef = self.rdef(subjtype, tschema)
4045
f4a52abb6f4f cw 3.6 api update
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4037
diff changeset
   440
                if not rdef.has_perm(session, action, **kwargs):
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   441
                    return False
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   442
        elif objtype:
4004
c52619c738a5 api renaming update
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4003
diff changeset
   443
            for tschema in self.targets(objtype, 'object'):
c52619c738a5 api renaming update
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4003
diff changeset
   444
                rdef = self.rdef(tschema, objtype)
c52619c738a5 api renaming update
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4003
diff changeset
   445
                if not rdef.has_perm(session, action, **kwargs):
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   446
                    return False
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   447
        else:
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   448
            for rdef in self.rdefs.itervalues():
4004
c52619c738a5 api renaming update
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4003
diff changeset
   449
                if not rdef.has_perm(session, action, **kwargs):
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   450
                    return False
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   451
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   452
    @deprecated('use .rdef(subjtype, objtype).role_cardinality(role)')
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   453
    def cardinality(self, subjtype, objtype, target):
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   454
        return self.rdef(subjtype, objtype).role_cardinality(target)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   455
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   456
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   457
class CubicWebSchema(Schema):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   458
    """set of entities and relations schema defining the possible data sets
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   459
    used in an application
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   460
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   461
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   462
    :type name: str
2476
1294a6bdf3bf application -> instance where it makes sense
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2460
diff changeset
   463
    :ivar name: name of the schema, usually the instance identifier
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   464
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   465
    :type base: str
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   466
    :ivar base: path of the directory where the schema is defined
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   467
    """
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   468
    reading_from_database = False
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   469
    entity_class = CubicWebEntitySchema
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   470
    relation_class = CubicWebRelationSchema
2958
44e5446b649b no inference for the identity relation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2926
diff changeset
   471
    no_specialization_inference = ('identity',)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   472
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   473
    def __init__(self, *args, **kwargs):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   474
        self._eid_index = {}
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   475
        super(CubicWebSchema, self).__init__(*args, **kwargs)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   476
        ybo.register_base_types(self)
2300
c8151d004e06 meta has been drop
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2293
diff changeset
   477
        rschema = self.add_relation_type(ybo.RelationType('eid'))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   478
        rschema.final = True
2300
c8151d004e06 meta has been drop
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2293
diff changeset
   479
        rschema = self.add_relation_type(ybo.RelationType('has_text'))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   480
        rschema.final = True
2300
c8151d004e06 meta has been drop
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2293
diff changeset
   481
        rschema = self.add_relation_type(ybo.RelationType('identity'))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   482
        rschema.final = False
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   483
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   484
    def add_entity_type(self, edef):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   485
        edef.name = edef.name.encode()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   486
        edef.name = bw_normalize_etype(edef.name)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   487
        assert re.match(r'[A-Z][A-Za-z0-9]*[a-z]+[0-9]*$', edef.name), repr(edef.name)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   488
        eschema = super(CubicWebSchema, self).add_entity_type(edef)
3689
deb13e88e037 follow yams 0.25 api changes to improve performance
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3554
diff changeset
   489
        if not eschema.final:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   490
            # automatically add the eid relation to non final entity types
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   491
            rdef = ybo.RelationDefinition(eschema.type, 'eid', 'Int',
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   492
                                          cardinality='11', uid=True)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   493
            self.add_relation_def(rdef)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   494
            rdef = ybo.RelationDefinition(eschema.type, 'identity', eschema.type)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   495
            self.add_relation_def(rdef)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   496
        self._eid_index[eschema.eid] = eschema
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   497
        return eschema
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   498
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   499
    def add_relation_type(self, rdef):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   500
        rdef.name = rdef.name.lower().encode()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   501
        rschema = super(CubicWebSchema, self).add_relation_type(rdef)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   502
        self._eid_index[rschema.eid] = rschema
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   503
        return rschema
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   504
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   505
    def add_relation_def(self, rdef):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   506
        """build a part of a relation schema
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   507
        (i.e. add a relation between two specific entity's types)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   508
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   509
        :type subject: str
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   510
        :param subject: entity's type that is subject of the relation
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   511
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   512
        :type rtype: str
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   513
        :param rtype: the relation's type (i.e. the name of the relation)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   514
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   515
        :type obj: str
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   516
        :param obj: entity's type that is object of the relation
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   517
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   518
        :rtype: RelationSchema
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   519
        :param: the newly created or just completed relation schema
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   520
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   521
        rdef.name = rdef.name.lower()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   522
        rdef.subject = bw_normalize_etype(rdef.subject)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   523
        rdef.object = bw_normalize_etype(rdef.object)
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   524
        rdefs = super(CubicWebSchema, self).add_relation_def(rdef)
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   525
        if rdefs:
1034
0356bbfb2f26 fix to pass arguments to base class
sylvain.thenault@logilab.fr
parents: 1016
diff changeset
   526
            try:
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   527
                self._eid_index[rdef.eid] = rdefs
1034
0356bbfb2f26 fix to pass arguments to base class
sylvain.thenault@logilab.fr
parents: 1016
diff changeset
   528
            except AttributeError:
0356bbfb2f26 fix to pass arguments to base class
sylvain.thenault@logilab.fr
parents: 1016
diff changeset
   529
                pass # not a serialized schema
4003
b9436fe77c9e fix bad merge
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 3998
diff changeset
   530
        return rdefs
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   531
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   532
    def del_relation_type(self, rtype):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   533
        rschema = self.rschema(rtype)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   534
        self._eid_index.pop(rschema.eid, None)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   535
        super(CubicWebSchema, self).del_relation_type(rtype)
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   536
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   537
    def del_relation_def(self, subjtype, rtype, objtype):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   538
        for k, v in self._eid_index.items():
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   539
            if not isinstance(v, RelationDefinitionSchema):
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   540
                continue
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   541
            if v.subject == subjtype and v.rtype == rtype and v.object == objtype:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   542
                del self._eid_index[k]
2718
3a56b87bb5d6 [schema] break when found
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2716
diff changeset
   543
                break
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   544
        super(CubicWebSchema, self).del_relation_def(subjtype, rtype, objtype)
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   545
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   546
    def del_entity_type(self, etype):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   547
        eschema = self.eschema(etype)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   548
        self._eid_index.pop(eschema.eid, None)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   549
        # deal with has_text first, else its automatic deletion (see above)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   550
        # may trigger an error in ancestor's del_entity_type method
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   551
        if 'has_text' in eschema.subject_relations():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   552
            self.del_relation_def(etype, 'has_text', 'String')
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   553
        super(CubicWebSchema, self).del_entity_type(etype)
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   554
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   555
    def schema_by_eid(self, eid):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   556
        return self._eid_index[eid]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   557
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   558
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   559
# Possible constraints ########################################################
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   560
3978
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   561
class BaseRQLConstraint(BaseConstraint):
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   562
    """base class for rql constraints
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   563
    """
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   564
3961
d1cbf77db999 fix RQLUniqueConstraint behaviour by using a DISTINCT query and allowing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   565
    def __init__(self, restriction, mainvars=None):
3963
0d592677e55f nicer mainvars/expression handling when initializing rql constraints
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3961
diff changeset
   566
        self.restriction = normalize_expression(restriction)
3961
d1cbf77db999 fix RQLUniqueConstraint behaviour by using a DISTINCT query and allowing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   567
        if mainvars is None:
d1cbf77db999 fix RQLUniqueConstraint behaviour by using a DISTINCT query and allowing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   568
            mainvars = guess_rrqlexpr_mainvars(restriction)
3963
0d592677e55f nicer mainvars/expression handling when initializing rql constraints
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3961
diff changeset
   569
        else:
0d592677e55f nicer mainvars/expression handling when initializing rql constraints
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3961
diff changeset
   570
            normmainvars = []
0d592677e55f nicer mainvars/expression handling when initializing rql constraints
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3961
diff changeset
   571
            for mainvar in mainvars.split(','):
0d592677e55f nicer mainvars/expression handling when initializing rql constraints
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3961
diff changeset
   572
                mainvar = mainvar.strip()
0d592677e55f nicer mainvars/expression handling when initializing rql constraints
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3961
diff changeset
   573
                if not mainvar.isalpha():
0d592677e55f nicer mainvars/expression handling when initializing rql constraints
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3961
diff changeset
   574
                    raise Exception('bad mainvars %s' % mainvars)
0d592677e55f nicer mainvars/expression handling when initializing rql constraints
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3961
diff changeset
   575
                normmainvars.append(mainvar)
0d592677e55f nicer mainvars/expression handling when initializing rql constraints
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3961
diff changeset
   576
            assert mainvars, 'bad mainvars %s' % mainvars
0d592677e55f nicer mainvars/expression handling when initializing rql constraints
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3961
diff changeset
   577
            mainvars = ','.join(sorted(normmainvars))
3961
d1cbf77db999 fix RQLUniqueConstraint behaviour by using a DISTINCT query and allowing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   578
        self.mainvars = mainvars
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   579
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   580
    def serialize(self):
3961
d1cbf77db999 fix RQLUniqueConstraint behaviour by using a DISTINCT query and allowing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   581
        # start with a comma for bw compat, see below
d1cbf77db999 fix RQLUniqueConstraint behaviour by using a DISTINCT query and allowing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   582
        return ';' + self.mainvars + ';' + self.restriction
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   583
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   584
    def deserialize(cls, value):
3961
d1cbf77db999 fix RQLUniqueConstraint behaviour by using a DISTINCT query and allowing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   585
        # XXX < 3.5.10 bw compat
d1cbf77db999 fix RQLUniqueConstraint behaviour by using a DISTINCT query and allowing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   586
        if not value.startswith(';'):
d1cbf77db999 fix RQLUniqueConstraint behaviour by using a DISTINCT query and allowing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   587
            return cls(value)
d1cbf77db999 fix RQLUniqueConstraint behaviour by using a DISTINCT query and allowing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   588
        _, mainvars, restriction = value.split(';', 2)
d1cbf77db999 fix RQLUniqueConstraint behaviour by using a DISTINCT query and allowing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   589
        return cls(restriction, mainvars)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   590
    deserialize = classmethod(deserialize)
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   591
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   592
    def check(self, entity, rtype, value):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   593
        """return true if the value satisfy the constraint, else false"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   594
        # implemented as a hook in the repository
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   595
        return 1
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   596
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   597
    def repo_check(self, session, eidfrom, rtype, eidto):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   598
        """raise ValidationError if the relation doesn't satisfy the constraint
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   599
        """
3554
26e586f3c15c [schema] make RQL* constraints usable w/ attributes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3347
diff changeset
   600
        pass # this is a vocabulary constraint, not enforce XXX why?
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   601
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   602
    def __str__(self):
3965
94f95928f5ae nicer __str__ and __repr__ methods on rql constraints
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3964
diff changeset
   603
        return '%s(Any %s WHERE %s)' % (self.__class__.__name__, self.mainvars,
94f95928f5ae nicer __str__ and __repr__ methods on rql constraints
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3964
diff changeset
   604
                                        self.restriction)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   605
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   606
    def __repr__(self):
3965
94f95928f5ae nicer __str__ and __repr__ methods on rql constraints
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3964
diff changeset
   607
        return '<%s @%#x>' % (self.__str__(), id(self))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   608
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   609
3978
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   610
class RQLVocabularyConstraint(BaseRQLConstraint):
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   611
    """the rql vocabulary constraint :
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   612
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   613
    limit the proposed values to a set of entities returned by a rql query,
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   614
    but this is not enforced at the repository level
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   615
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   616
     restriction is additional rql restriction that will be added to
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   617
     a predefined query, where the S and O variables respectivly represent
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   618
     the subject and the object of the relation
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   619
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   620
     mainvars is a string that should be used as selection variable (eg
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   621
     `'Any %s WHERE ...' % mainvars`). If not specified, an attempt will be
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   622
     done to guess it according to variable used in the expression.
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   623
    """
3978
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   624
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   625
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   626
class RepoEnforcedRQLConstraintMixIn(object):
3961
d1cbf77db999 fix RQLUniqueConstraint behaviour by using a DISTINCT query and allowing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   627
3964
21387ffb0731 refactor so that we can specify an extra argument to constraints which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3963
diff changeset
   628
    def __init__(self, restriction, mainvars=None, msg=None):
3978
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   629
        super(RepoEnforcedRQLConstraintMixIn, self).__init__(restriction, mainvars)
3964
21387ffb0731 refactor so that we can specify an extra argument to constraints which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3963
diff changeset
   630
        self.msg = msg
21387ffb0731 refactor so that we can specify an extra argument to constraints which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3963
diff changeset
   631
21387ffb0731 refactor so that we can specify an extra argument to constraints which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3963
diff changeset
   632
    def serialize(self):
3968
e8dbad65a7a2 fix format string
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 3967
diff changeset
   633
        # start with a semicolon for bw compat, see below
e8dbad65a7a2 fix format string
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 3967
diff changeset
   634
        return ';%s;%s\n%s' % (self.mainvars, self.restriction,
3964
21387ffb0731 refactor so that we can specify an extra argument to constraints which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3963
diff changeset
   635
                               self.msg or '')
21387ffb0731 refactor so that we can specify an extra argument to constraints which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3963
diff changeset
   636
21387ffb0731 refactor so that we can specify an extra argument to constraints which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3963
diff changeset
   637
    def deserialize(cls, value):
21387ffb0731 refactor so that we can specify an extra argument to constraints which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3963
diff changeset
   638
        # XXX < 3.5.10 bw compat
21387ffb0731 refactor so that we can specify an extra argument to constraints which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3963
diff changeset
   639
        if not value.startswith(';'):
21387ffb0731 refactor so that we can specify an extra argument to constraints which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3963
diff changeset
   640
            return cls(value)
21387ffb0731 refactor so that we can specify an extra argument to constraints which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3963
diff changeset
   641
        value, msg = value.split('\n', 1)
21387ffb0731 refactor so that we can specify an extra argument to constraints which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3963
diff changeset
   642
        _, mainvars, restriction = value.split(';', 2)
21387ffb0731 refactor so that we can specify an extra argument to constraints which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3963
diff changeset
   643
        return cls(restriction, mainvars, msg)
21387ffb0731 refactor so that we can specify an extra argument to constraints which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3963
diff changeset
   644
    deserialize = classmethod(deserialize)
21387ffb0731 refactor so that we can specify an extra argument to constraints which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3963
diff changeset
   645
3554
26e586f3c15c [schema] make RQL* constraints usable w/ attributes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3347
diff changeset
   646
    def repo_check(self, session, eidfrom, rtype, eidto=None):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   647
        """raise ValidationError if the relation doesn't satisfy the constraint
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   648
        """
3978
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   649
        if not self.match_condition(session, eidfrom, eidto):
3964
21387ffb0731 refactor so that we can specify an extra argument to constraints which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3963
diff changeset
   650
            # XXX at this point if both or neither of S and O are in mainvar we
21387ffb0731 refactor so that we can specify an extra argument to constraints which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3963
diff changeset
   651
            # dunno if the validation error `occured` on eidfrom or eidto (from
21387ffb0731 refactor so that we can specify an extra argument to constraints which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3963
diff changeset
   652
            # user interface point of view)
21387ffb0731 refactor so that we can specify an extra argument to constraints which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3963
diff changeset
   653
            if eidto is None or 'S' in self.mainvars or not 'O' in self.mainvars:
21387ffb0731 refactor so that we can specify an extra argument to constraints which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3963
diff changeset
   654
                maineid = eidfrom
21387ffb0731 refactor so that we can specify an extra argument to constraints which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3963
diff changeset
   655
            else:
21387ffb0731 refactor so that we can specify an extra argument to constraints which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3963
diff changeset
   656
                maineid = eidto
21387ffb0731 refactor so that we can specify an extra argument to constraints which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3963
diff changeset
   657
            if self.msg:
21387ffb0731 refactor so that we can specify an extra argument to constraints which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3963
diff changeset
   658
                msg = session._(self.msg)
21387ffb0731 refactor so that we can specify an extra argument to constraints which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3963
diff changeset
   659
            else:
21387ffb0731 refactor so that we can specify an extra argument to constraints which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3963
diff changeset
   660
                msg = '%(constraint)s %(restriction)s failed' % {
21387ffb0731 refactor so that we can specify an extra argument to constraints which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3963
diff changeset
   661
                    'constraint':  session._(self.type()),
21387ffb0731 refactor so that we can specify an extra argument to constraints which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3963
diff changeset
   662
                    'restriction': self.restriction}
21387ffb0731 refactor so that we can specify an extra argument to constraints which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3963
diff changeset
   663
            raise ValidationError(maineid, {rtype: msg})
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   664
3978
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   665
    def exec_query(self, session, eidfrom, eidto):
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   666
        if eidto is None:
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   667
            # checking constraint for an attribute relation
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   668
            restriction = 'S eid %(s)s, ' + self.restriction
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   669
            args, ck = {'s': eidfrom}, 's'
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   670
        else:
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   671
            restriction = 'S eid %(s)s, O eid %(o)s, ' + self.restriction
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   672
            args, ck = {'s': eidfrom, 'o': eidto}, ('s', 'o')
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   673
        rql = 'Any %s WHERE %s' % (self.mainvars,  restriction)
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   674
        if self.distinct_query:
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   675
            rql = 'DISTINCT ' + rql
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   676
        return session.unsafe_execute(rql, args, ck, build_descr=False)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   677
3978
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   678
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   679
class RQLConstraint(RepoEnforcedRQLConstraintMixIn, RQLVocabularyConstraint):
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   680
    """the rql constraint is similar to the RQLVocabularyConstraint but
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   681
    are also enforced at the repository level
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   682
    """
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   683
    distinct_query = False
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   684
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   685
    def match_condition(self, session, eidfrom, eidto):
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   686
        return self.exec_query(session, eidfrom, eidto)
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   687
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   688
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   689
class RQLUniqueConstraint(RepoEnforcedRQLConstraintMixIn, BaseRQLConstraint):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   690
    """the unique rql constraint check that the result of the query isn't
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   691
    greater than one
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   692
    """
3961
d1cbf77db999 fix RQLUniqueConstraint behaviour by using a DISTINCT query and allowing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   693
    distinct_query = True
d1cbf77db999 fix RQLUniqueConstraint behaviour by using a DISTINCT query and allowing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   694
3985
d5bf894fcf02 add some notes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3980
diff changeset
   695
    # XXX turns mainvars into a required argument in __init__, since we've no
d5bf894fcf02 add some notes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3980
diff changeset
   696
    #     way to guess it correctly (eg if using S,O or U the constraint will
d5bf894fcf02 add some notes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3980
diff changeset
   697
    #     always be satisfied since we've to use a DISTINCT query)
d5bf894fcf02 add some notes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3980
diff changeset
   698
3978
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   699
    def match_condition(self, session, eidfrom, eidto):
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   700
        return len(self.exec_query(session, eidfrom, eidto)) <= 1
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   701
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   702
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   703
class RQLExpression(object):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   704
    def __init__(self, expression, mainvars, eid):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   705
        self.eid = eid # eid of the entity representing this rql expression
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   706
        if not isinstance(mainvars, unicode):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   707
            mainvars = unicode(mainvars)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   708
        self.mainvars = mainvars
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   709
        self.expression = normalize_expression(expression)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   710
        try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   711
            self.rqlst = parse(self.full_rql, print_errors=False).children[0]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   712
        except RQLSyntaxError:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   713
            raise RQLSyntaxError(expression)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   714
        for mainvar in mainvars.split(','):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   715
            if len(self.rqlst.defined_vars[mainvar].references()) <= 2:
2142
098aa2075903 include_schema_files is useless
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   716
                _LOGGER.warn('You did not use the %s variable in your RQL '
098aa2075903 include_schema_files is useless
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   717
                             'expression %s', mainvar, self)
3825
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3824
diff changeset
   718
        # syntax tree used by read security (inserted in queries when necessary)
3240
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2967
diff changeset
   719
        self.snippet_rqlst = parse(self.minimal_rql, print_errors=False).children[0]
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   720
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   721
    def __str__(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   722
        return self.full_rql
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   723
    def __repr__(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   724
        return '%s(%s)' % (self.__class__.__name__, self.full_rql)
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   725
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   726
    def __cmp__(self, other):
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   727
        if hasattr(other, 'expression'):
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   728
            return cmp(other.expression, self.expression)
4066
0555f170c4d1 __cmp__ should *NOT* return False when different
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4045
diff changeset
   729
        return -1
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   730
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   731
    def __deepcopy__(self, memo):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   732
        return self.__class__(self.expression, self.mainvars)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   733
    def __getstate__(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   734
        return (self.expression, self.mainvars)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   735
    def __setstate__(self, state):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   736
        self.__init__(*state)
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   737
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   738
    @cached
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   739
    def transform_has_permission(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   740
        found = None
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   741
        rqlst = self.rqlst
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   742
        for var in rqlst.defined_vars.itervalues():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   743
            for varref in var.references():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   744
                rel = varref.relation()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   745
                if rel is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   746
                    continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   747
                try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   748
                    prefix, action, suffix = rel.r_type.split('_')
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   749
                except ValueError:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   750
                    continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   751
                if prefix != 'has' or suffix != 'permission' or \
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   752
                       not action in ('add', 'delete', 'update', 'read'):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   753
                    continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   754
                if found is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   755
                    found = []
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   756
                    rqlst.save_state()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   757
                assert rel.children[0].name == 'U'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   758
                objvar = rel.children[1].children[0].variable
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   759
                rqlst.remove_node(rel)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   760
                selected = [v.name for v in rqlst.get_selected_variables()]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   761
                if objvar.name not in selected:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   762
                    colindex = len(selected)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   763
                    rqlst.add_selected(objvar)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   764
                else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   765
                    colindex = selected.index(objvar.name)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   766
                found.append((action, objvar, colindex))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   767
                # remove U eid %(u)s if U is not used in any other relation
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   768
                uvrefs = rqlst.defined_vars['U'].references()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   769
                if len(uvrefs) == 1:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   770
                    rqlst.remove_node(uvrefs[0].relation())
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   771
        if found is not None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   772
            rql = rqlst.as_string()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   773
            if len(rqlst.selection) == 1 and isinstance(rqlst.where, nodes.Relation):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   774
                # only "Any X WHERE X eid %(x)s" remaining, no need to execute the rql
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   775
                keyarg = rqlst.selection[0].name.lower()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   776
            else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   777
                keyarg = None
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   778
            rqlst.recover()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   779
            return rql, found, keyarg
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   780
        return rqlst.as_string(), None, None
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   781
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   782
    def _check(self, session, **kwargs):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   783
        """return True if the rql expression is matching the given relation
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   784
        between fromeid and toeid
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   785
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   786
        session may actually be a request as well
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   787
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   788
        if self.eid is not None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   789
            key = (self.eid, tuple(sorted(kwargs.iteritems())))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   790
            try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   791
                return session.local_perm_cache[key]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   792
            except KeyError:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   793
                pass
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   794
        rql, has_perm_defs, keyarg = self.transform_has_permission()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   795
        if keyarg is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   796
            # on the server side, use unsafe_execute, but this is not available
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   797
            # on the client side (session is actually a request)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   798
            execute = getattr(session, 'unsafe_execute', session.execute)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   799
            # XXX what if 'u' in kwargs
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   800
            cachekey = kwargs.keys()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   801
            kwargs['u'] = session.user.eid
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   802
            try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   803
                rset = execute(rql, kwargs, cachekey, build_descr=True)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   804
            except NotImplementedError:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   805
                self.critical('cant check rql expression, unsupported rql %s', rql)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   806
                if self.eid is not None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   807
                    session.local_perm_cache[key] = False
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   808
                return False
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   809
            except TypeResolverException, ex:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   810
                # some expression may not be resolvable with current kwargs
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   811
                # (type conflict)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   812
                self.warning('%s: %s', rql, str(ex))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   813
                if self.eid is not None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   814
                    session.local_perm_cache[key] = False
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   815
                return False
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   816
        else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   817
            rset = session.eid_rset(kwargs[keyarg])
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   818
        # if no special has_*_permission relation in the rql expression, just
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   819
        # check the result set contains something
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   820
        if has_perm_defs is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   821
            if rset:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   822
                if self.eid is not None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   823
                    session.local_perm_cache[key] = True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   824
                return True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   825
        elif rset:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   826
            # check every special has_*_permission relation is satisfied
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   827
            get_eschema = session.vreg.schema.eschema
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   828
            try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   829
                for eaction, var, col in has_perm_defs:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   830
                    for i in xrange(len(rset)):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   831
                        eschema = get_eschema(rset.description[i][col])
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   832
                        eschema.check_perm(session, eaction, eid=rset[i][col])
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   833
                if self.eid is not None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   834
                    session.local_perm_cache[key] = True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   835
                return True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   836
            except Unauthorized:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   837
                pass
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   838
        if self.eid is not None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   839
            session.local_perm_cache[key] = False
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   840
        return False
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   841
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   842
    @property
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   843
    def minimal_rql(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   844
        return 'Any %s WHERE %s' % (self.mainvars, self.expression)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   845
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   846
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   847
class ERQLExpression(RQLExpression):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   848
    def __init__(self, expression, mainvars=None, eid=None):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   849
        RQLExpression.__init__(self, expression, mainvars or 'X', eid)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   850
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   851
    @property
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   852
    def full_rql(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   853
        rql = self.minimal_rql
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   854
        rqlst = getattr(self, 'rqlst', None) # may be not set yet
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   855
        if rqlst is not None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   856
            defined = rqlst.defined_vars
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   857
        else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   858
            defined = set(split_expression(self.expression))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   859
        if 'X' in defined:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   860
            rql += ', X eid %(x)s'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   861
        if 'U' in defined:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   862
            rql += ', U eid %(u)s'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   863
        return rql
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   864
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   865
    def check(self, session, eid=None):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   866
        if 'X' in self.rqlst.defined_vars:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   867
            if eid is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   868
                return False
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   869
            return self._check(session, x=eid)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   870
        return self._check(session)
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   871
3961
d1cbf77db999 fix RQLUniqueConstraint behaviour by using a DISTINCT query and allowing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   872
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   873
class RRQLExpression(RQLExpression):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   874
    def __init__(self, expression, mainvars=None, eid=None):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   875
        if mainvars is None:
3961
d1cbf77db999 fix RQLUniqueConstraint behaviour by using a DISTINCT query and allowing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   876
            mainvars = guess_rrqlexpr_mainvars(expression)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   877
        RQLExpression.__init__(self, expression, mainvars, eid)
3827
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   878
        # graph of links between variable, used by rql rewriter
3826
0c0c051863cb close #511810: bad rql generated when looking for vocabulary for a relation on an entity which doesn't exist (yet)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3825
diff changeset
   879
        self.vargraph = {}
0c0c051863cb close #511810: bad rql generated when looking for vocabulary for a relation on an entity which doesn't exist (yet)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3825
diff changeset
   880
        for relation in self.rqlst.get_nodes(nodes.Relation):
0c0c051863cb close #511810: bad rql generated when looking for vocabulary for a relation on an entity which doesn't exist (yet)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3825
diff changeset
   881
            try:
0c0c051863cb close #511810: bad rql generated when looking for vocabulary for a relation on an entity which doesn't exist (yet)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3825
diff changeset
   882
                rhsvarname = relation.children[1].children[0].variable.name
0c0c051863cb close #511810: bad rql generated when looking for vocabulary for a relation on an entity which doesn't exist (yet)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3825
diff changeset
   883
                lhsvarname = relation.children[0].name
0c0c051863cb close #511810: bad rql generated when looking for vocabulary for a relation on an entity which doesn't exist (yet)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3825
diff changeset
   884
            except AttributeError:
0c0c051863cb close #511810: bad rql generated when looking for vocabulary for a relation on an entity which doesn't exist (yet)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3825
diff changeset
   885
                pass
0c0c051863cb close #511810: bad rql generated when looking for vocabulary for a relation on an entity which doesn't exist (yet)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3825
diff changeset
   886
            else:
0c0c051863cb close #511810: bad rql generated when looking for vocabulary for a relation on an entity which doesn't exist (yet)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3825
diff changeset
   887
                self.vargraph.setdefault(lhsvarname, []).append(rhsvarname)
0c0c051863cb close #511810: bad rql generated when looking for vocabulary for a relation on an entity which doesn't exist (yet)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3825
diff changeset
   888
                self.vargraph.setdefault(rhsvarname, []).append(lhsvarname)
0c0c051863cb close #511810: bad rql generated when looking for vocabulary for a relation on an entity which doesn't exist (yet)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3825
diff changeset
   889
                #self.vargraph[(lhsvarname, rhsvarname)] = relation.r_type
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   890
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   891
    @property
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   892
    def full_rql(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   893
        rql = self.minimal_rql
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   894
        rqlst = getattr(self, 'rqlst', None) # may be not set yet
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   895
        if rqlst is not None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   896
            defined = rqlst.defined_vars
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   897
        else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   898
            defined = set(split_expression(self.expression))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   899
        if 'S' in defined:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   900
            rql += ', S eid %(s)s'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   901
        if 'O' in defined:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   902
            rql += ', O eid %(o)s'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   903
        if 'U' in defined:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   904
            rql += ', U eid %(u)s'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   905
        return rql
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   906
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   907
    def check(self, session, fromeid=None, toeid=None):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   908
        kwargs = {}
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   909
        if 'S' in self.rqlst.defined_vars:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   910
            if fromeid is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   911
                return False
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   912
            kwargs['s'] = fromeid
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   913
        if 'O' in self.rqlst.defined_vars:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   914
            if toeid is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   915
                return False
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   916
            kwargs['o'] = toeid
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   917
        return self._check(session, **kwargs)
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   918
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   919
629
59b6542f5729 provide a new WorkflowableEntityType base class (will be refactored later, maybe with schema interfaces)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 628
diff changeset
   920
# workflow extensions #########################################################
2926
4484387ed012 when adding/removing cubes, we should add/remove entity types in correct order if one inherits from another
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
   921
2460
ce1a7ffc6c90 fix a couple NameErrors
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2459
diff changeset
   922
from yams.buildobjs import _add_relation as yams_add_relation
629
59b6542f5729 provide a new WorkflowableEntityType base class (will be refactored later, maybe with schema interfaces)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 628
diff changeset
   923
59b6542f5729 provide a new WorkflowableEntityType base class (will be refactored later, maybe with schema interfaces)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 628
diff changeset
   924
class workflowable_definition(ybo.metadefinition):
59b6542f5729 provide a new WorkflowableEntityType base class (will be refactored later, maybe with schema interfaces)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 628
diff changeset
   925
    """extends default EntityType's metaclass to add workflow relations
59b6542f5729 provide a new WorkflowableEntityType base class (will be refactored later, maybe with schema interfaces)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 628
diff changeset
   926
    (i.e. in_state and wf_info_for).
59b6542f5729 provide a new WorkflowableEntityType base class (will be refactored later, maybe with schema interfaces)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 628
diff changeset
   927
    This is the default metaclass for WorkflowableEntityType
59b6542f5729 provide a new WorkflowableEntityType base class (will be refactored later, maybe with schema interfaces)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 628
diff changeset
   928
    """
59b6542f5729 provide a new WorkflowableEntityType base class (will be refactored later, maybe with schema interfaces)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 628
diff changeset
   929
    def __new__(mcs, name, bases, classdict):
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
   930
        abstract = classdict.pop('__abstract__', False)
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
   931
        cls = super(workflowable_definition, mcs).__new__(mcs, name, bases,
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
   932
                                                          classdict)
629
59b6542f5729 provide a new WorkflowableEntityType base class (will be refactored later, maybe with schema interfaces)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 628
diff changeset
   933
        if not abstract:
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
   934
            make_workflowable(cls)
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
   935
        return cls
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
   936
2957
2daabf4c646e [schema] make_workflowable now take an option description for the in_state relation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2931
diff changeset
   937
def make_workflowable(cls, in_state_descr=None):
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
   938
    existing_rels = set(rdef.name for rdef in cls.__relations__)
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
   939
    # let relation types defined in cw.schemas.workflow carrying
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
   940
    # cardinality, constraints and other relation definition properties
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
   941
    if 'custom_workflow' not in existing_rels:
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
   942
        rdef = ybo.SubjectRelation('Workflow')
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
   943
        yams_add_relation(cls.__relations__, rdef, 'custom_workflow')
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
   944
    if 'in_state' not in existing_rels:
2957
2daabf4c646e [schema] make_workflowable now take an option description for the in_state relation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2931
diff changeset
   945
        rdef = ybo.SubjectRelation('State', description=in_state_descr)
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
   946
        yams_add_relation(cls.__relations__, rdef, 'in_state')
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
   947
    if 'wf_info_for' not in existing_rels:
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
   948
        rdef = ybo.ObjectRelation('TrInfo')
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
   949
        yams_add_relation(cls.__relations__, rdef, 'wf_info_for')
629
59b6542f5729 provide a new WorkflowableEntityType base class (will be refactored later, maybe with schema interfaces)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 628
diff changeset
   950
59b6542f5729 provide a new WorkflowableEntityType base class (will be refactored later, maybe with schema interfaces)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 628
diff changeset
   951
class WorkflowableEntityType(ybo.EntityType):
59b6542f5729 provide a new WorkflowableEntityType base class (will be refactored later, maybe with schema interfaces)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 628
diff changeset
   952
    __metaclass__ = workflowable_definition
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
   953
    __abstract__ = True
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   954
629
59b6542f5729 provide a new WorkflowableEntityType base class (will be refactored later, maybe with schema interfaces)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 628
diff changeset
   955
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   956
# schema loading ##############################################################
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   957
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   958
CONSTRAINTS['RQLConstraint'] = RQLConstraint
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   959
CONSTRAINTS['RQLUniqueConstraint'] = RQLUniqueConstraint
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   960
CONSTRAINTS['RQLVocabularyConstraint'] = RQLVocabularyConstraint
3980
b17cf4a2e09e this constraint is actually unusable in yams schema for cw
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3979
diff changeset
   961
CONSTRAINTS.pop('MultipleStaticVocabularyConstraint', None) # don't want this in cw yams schema
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   962
PyFileReader.context.update(CONSTRAINTS)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   963
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   964
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   965
class BootstrapSchemaLoader(SchemaLoader):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   966
    """cubicweb specific schema loader, loading only schema necessary to read
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   967
    the persistent schema
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   968
    """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   969
    schemacls = CubicWebSchema
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   970
1034
0356bbfb2f26 fix to pass arguments to base class
sylvain.thenault@logilab.fr
parents: 1016
diff changeset
   971
    def load(self, config, path=(), **kwargs):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   972
        """return a Schema instance from the schema definition read
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   973
        from <directory>
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   974
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   975
        return super(BootstrapSchemaLoader, self).load(
1034
0356bbfb2f26 fix to pass arguments to base class
sylvain.thenault@logilab.fr
parents: 1016
diff changeset
   976
            path, config.appid, register_base_types=False, **kwargs)
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   977
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   978
    def _load_definition_files(self, cubes=None):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   979
        # bootstraping, ignore cubes
2735
39c942241b48 no need for lib_directory
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2730
diff changeset
   980
        filepath = join(cubicweb.CW_SOFTWARE_ROOT, 'schemas', 'bootstrap.py')
2142
098aa2075903 include_schema_files is useless
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   981
        self.info('loading %s', filepath)
098aa2075903 include_schema_files is useless
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   982
        self.handle_file(filepath)
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   983
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   984
    def unhandled_file(self, filepath):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   985
        """called when a file without handler associated has been found"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   986
        self.warning('ignoring file %r', filepath)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   987
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   988
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   989
class CubicWebSchemaLoader(BootstrapSchemaLoader):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   990
    """cubicweb specific schema loader, automatically adding metadata to the
2476
1294a6bdf3bf application -> instance where it makes sense
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2460
diff changeset
   991
    instance's schema
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   992
    """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   993
1034
0356bbfb2f26 fix to pass arguments to base class
sylvain.thenault@logilab.fr
parents: 1016
diff changeset
   994
    def load(self, config, **kwargs):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   995
        """return a Schema instance from the schema definition read
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   996
        from <directory>
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   997
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   998
        self.info('loading %s schemas', ', '.join(config.cubes()))
2782
998f24dabd0d compute extrapath, necessary for proper schema module detection when CW_CUBES_PATH is set
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2742
diff changeset
   999
        self.extrapath = {}
998f24dabd0d compute extrapath, necessary for proper schema module detection when CW_CUBES_PATH is set
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2742
diff changeset
  1000
        for cubesdir in config.cubes_search_path():
998f24dabd0d compute extrapath, necessary for proper schema module detection when CW_CUBES_PATH is set
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2742
diff changeset
  1001
            if cubesdir != config.CUBES_DIR:
998f24dabd0d compute extrapath, necessary for proper schema module detection when CW_CUBES_PATH is set
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2742
diff changeset
  1002
                self.extrapath[cubesdir] = 'cubes'
372
a8a975a88368 check apphome is not None
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 0
diff changeset
  1003
        if config.apphome:
2598
a66fe74bd9fc [R schema] dont give an iterator, it's a trap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2596
diff changeset
  1004
            path = tuple(reversed([config.apphome] + config.cubes_path()))
372
a8a975a88368 check apphome is not None
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 0
diff changeset
  1005
        else:
2598
a66fe74bd9fc [R schema] dont give an iterator, it's a trap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2596
diff changeset
  1006
            path = tuple(reversed(config.cubes_path()))
2526
40e41eb34a7d we've to call cleanup_sys_modules manually for proper schema modules cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2476
diff changeset
  1007
        try:
40e41eb34a7d we've to call cleanup_sys_modules manually for proper schema modules cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2476
diff changeset
  1008
            return super(CubicWebSchemaLoader, self).load(config, path=path, **kwargs)
40e41eb34a7d we've to call cleanup_sys_modules manually for proper schema modules cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2476
diff changeset
  1009
        finally:
40e41eb34a7d we've to call cleanup_sys_modules manually for proper schema modules cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2476
diff changeset
  1010
            # we've to cleanup modules imported from cubicweb.schemas as well
2735
39c942241b48 no need for lib_directory
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2730
diff changeset
  1011
            cleanup_sys_modules([join(cubicweb.CW_SOFTWARE_ROOT, 'schemas')])
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1012
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1013
    def _load_definition_files(self, cubes):
2741
148d0cea1fb5 [schema] oops
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2736
diff changeset
  1014
        for filepath in (join(cubicweb.CW_SOFTWARE_ROOT, 'schemas', 'bootstrap.py'),
148d0cea1fb5 [schema] oops
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2736
diff changeset
  1015
                         join(cubicweb.CW_SOFTWARE_ROOT, 'schemas', 'base.py'),
148d0cea1fb5 [schema] oops
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2736
diff changeset
  1016
                         join(cubicweb.CW_SOFTWARE_ROOT, 'schemas', 'workflow.py'),
148d0cea1fb5 [schema] oops
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2736
diff changeset
  1017
                         join(cubicweb.CW_SOFTWARE_ROOT, 'schemas', 'Bookmark.py')):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1018
            self.info('loading %s', filepath)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1019
            self.handle_file(filepath)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1020
        for cube in cubes:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1021
            for filepath in self.get_schema_files(cube):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1022
                self.info('loading %s', filepath)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1023
                self.handle_file(filepath)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1024
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1025
2459
d088d0ff48a1 move RichString and co to yams, keeping only a small monkeypatch for cw-page-template here
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2456
diff changeset
  1026
set_log_methods(CubicWebSchemaLoader, getLogger('cubicweb.schemaloader'))
d088d0ff48a1 move RichString and co to yams, keeping only a small monkeypatch for cw-page-template here
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2456
diff changeset
  1027
set_log_methods(BootstrapSchemaLoader, getLogger('cubicweb.bootstrapschemaloader'))
d088d0ff48a1 move RichString and co to yams, keeping only a small monkeypatch for cw-page-template here
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2456
diff changeset
  1028
set_log_methods(RQLExpression, getLogger('cubicweb.schema'))
d088d0ff48a1 move RichString and co to yams, keeping only a small monkeypatch for cw-page-template here
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2456
diff changeset
  1029
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1030
# _() is just there to add messages to the catalog, don't care about actual
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1031
# translation
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1032
PERM_USE_TEMPLATE_FORMAT = _('use_template_format')
2459
d088d0ff48a1 move RichString and co to yams, keeping only a small monkeypatch for cw-page-template here
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2456
diff changeset
  1033
NEED_PERM_FORMATS = [_('text/cubicweb-page-template')]
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1034
2531
531ea4e7013e [cleanup] nicer imports
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2526
diff changeset
  1035
@monkeypatch(FormatConstraint)
3347
428f95118556 fix vocab param to avoid deprecation warning
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3287
diff changeset
  1036
def vocabulary(self, entity=None, form=None):
3401
f893f4f199fc use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3369
diff changeset
  1037
    cw = None
3347
428f95118556 fix vocab param to avoid deprecation warning
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3287
diff changeset
  1038
    if form is None and entity is not None:
3401
f893f4f199fc use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3369
diff changeset
  1039
        cw = entity._cw
3347
428f95118556 fix vocab param to avoid deprecation warning
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3287
diff changeset
  1040
    elif form is not None:
3401
f893f4f199fc use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3369
diff changeset
  1041
        cw = form._cw
f893f4f199fc use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3369
diff changeset
  1042
    if cw is not None and cw.user.has_permission(PERM_USE_TEMPLATE_FORMAT):
2459
d088d0ff48a1 move RichString and co to yams, keeping only a small monkeypatch for cw-page-template here
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2456
diff changeset
  1043
        return self.regular_formats + tuple(NEED_PERM_FORMATS)
d088d0ff48a1 move RichString and co to yams, keeping only a small monkeypatch for cw-page-template here
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2456
diff changeset
  1044
    return self.regular_formats
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1045
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1046
# XXX monkey patch PyFileReader.import_erschema until bw_normalize_etype is
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1047
# necessary
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1048
orig_import_erschema = PyFileReader.import_erschema
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1049
def bw_import_erschema(self, ertype, schemamod=None, instantiate=True):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1050
    return orig_import_erschema(self, bw_normalize_etype(ertype), schemamod, instantiate)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1051
PyFileReader.import_erschema = bw_import_erschema
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
  1052
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1053
# XXX itou for some Statement methods
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1054
from rql import stmts
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1055
orig_get_etype = stmts.ScopeNode.get_etype
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1056
def bw_get_etype(self, name):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1057
    return orig_get_etype(self, bw_normalize_etype(name))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1058
stmts.ScopeNode.get_etype = bw_get_etype
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1059
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1060
orig_add_main_variable_delete = stmts.Delete.add_main_variable
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1061
def bw_add_main_variable_delete(self, etype, vref):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1062
    return orig_add_main_variable_delete(self, bw_normalize_etype(etype), vref)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1063
stmts.Delete.add_main_variable = bw_add_main_variable_delete
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1064
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1065
orig_add_main_variable_insert = stmts.Insert.add_main_variable
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1066
def bw_add_main_variable_insert(self, etype, vref):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1067
    return orig_add_main_variable_insert(self, bw_normalize_etype(etype), vref)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1068
stmts.Insert.add_main_variable = bw_add_main_variable_insert
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1069
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1070
orig_set_statement_type = stmts.Select.set_statement_type
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1071
def bw_set_statement_type(self, etype):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1072
    return orig_set_statement_type(self, bw_normalize_etype(etype))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1073
stmts.Select.set_statement_type = bw_set_statement_type
2736
c5048502409f restore backward compat, still imported a lot
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2735
diff changeset
  1074
c5048502409f restore backward compat, still imported a lot
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2735
diff changeset
  1075
# XXX deprecated
3978
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
  1076
2736
c5048502409f restore backward compat, still imported a lot
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2735
diff changeset
  1077
from yams.constraints import format_constraint
2788
8d3dbe577d3a R put version info in deprecation warnings
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2782
diff changeset
  1078
format_constraint = deprecated('[3.4] use RichString instead of format_constraint')(format_constraint)
2736
c5048502409f restore backward compat, still imported a lot
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2735
diff changeset
  1079
from yams.buildobjs import RichString
3978
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
  1080
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
  1081
PyFileReader.context['ERQLExpression'] = yobsolete(ERQLExpression)
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
  1082
PyFileReader.context['RRQLExpression'] = yobsolete(RRQLExpression)
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
  1083
PyFileReader.context['WorkflowableEntityType'] = WorkflowableEntityType
2742
9439c61eb84c [bw compat] restore format_constraint into schema file context
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2741
diff changeset
  1084
PyFileReader.context['format_constraint'] = format_constraint