schema.py
author Stephanie Marcu <stephanie.marcu@logilab.fr>
Tue, 19 Jan 2010 17:50:48 +0100
changeset 4268 e9bed3bc1333
parent 4252 6c4f109c2b03
child 4434 101344a6ff9b
permissions -rw-r--r--
remove common/test/data directory from __pkginfo__, MANIFEST and debian rules to allow cubicweb installation
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
4212
ab6573088b4a update copyright: welcome 2010
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4132
diff changeset
     4
:copyright: 2001-2010 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(','):
4132
440d383367eb fix mainvars detection bug with EXISTS (paren, actually)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3985
diff changeset
   141
        for noparen in expr.split('('):
440d383367eb fix mainvars detection bug with EXISTS (paren, actually)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3985
diff changeset
   142
            for word in noparen.split():
440d383367eb fix mainvars detection bug with EXISTS (paren, actually)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3985
diff changeset
   143
                yield word
3978
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   144
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   145
def normalize_expression(rqlstring):
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   146
    """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
   147
    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
   148
    for instance)
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   149
    """
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   150
    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
   151
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   152
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   153
# Schema objects definition ###################################################
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   154
3471
8c57c71b859c can now give context to rschema.display_name(...)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3401
diff changeset
   155
def ERSchema_display_name(self, req, form='', context=None):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   156
    """return a internationalized string for the entity/relation type name in
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   157
    a given form
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   158
    """
3471
8c57c71b859c can now give context to rschema.display_name(...)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3401
diff changeset
   159
    return display_name(req, self.type, form, context)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   160
ERSchema.display_name = ERSchema_display_name
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   161
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   162
@cached
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   163
def get_groups(self, action):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   164
    """return the groups authorized to perform <action> on entities of
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   165
    this type
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   166
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   167
    :type action: str
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   168
    :param action: the name of a permission
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   169
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   170
    :rtype: tuple
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   171
    :return: names of the groups with the given permission
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   172
    """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   173
    assert action in self.ACTIONS, action
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   174
    #assert action in self._groups, '%s %s' % (self, action)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   175
    try:
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   176
        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
   177
    except KeyError:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   178
        return ()
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   179
PermissionMixIn.get_groups = get_groups
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   180
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   181
@cached
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   182
def get_rqlexprs(self, action):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   183
    """return the rql expressions representing queries to check the user is allowed
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   184
    to perform <action> on entities of this type
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   185
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   186
    :type action: str
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   187
    :param action: the name of a permission
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   188
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   189
    :rtype: tuple
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   190
    :return: the rql expressions with the given permission
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   191
    """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   192
    assert action in self.ACTIONS, action
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   193
    #assert action in self._rqlexprs, '%s %s' % (self, action)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   194
    try:
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   195
        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
   196
    except KeyError:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   197
        return ()
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   198
PermissionMixIn.get_rqlexprs = get_rqlexprs
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   199
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   200
orig_set_action_permissions = PermissionMixIn.set_action_permissions
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   201
def set_action_permissions(self, action, permissions):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   202
    """set the groups and rql expressions allowing to perform <action> on
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   203
    entities of this type
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   204
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   205
    :type action: str
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   206
    :param action: the name of a permission
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   207
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   208
    :type permissions: tuple
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   209
    :param permissions: the groups and rql expressions allowing the given action
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   210
    """
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   211
    orig_set_action_permissions(self, action, tuple(permissions))
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   212
    clear_cache(self, 'get_rqlexprs')
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   213
    clear_cache(self, 'get_groups')
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   214
PermissionMixIn.set_action_permissions = set_action_permissions
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   215
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   216
def has_local_role(self, action):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   217
    """return true if the action *may* be granted localy (eg either rql
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   218
    expressions or the owners group are used in security definition)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   219
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   220
    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
   221
    'add' action checking. Also find a better name would be nice.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   222
    """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   223
    assert action in self.ACTIONS, action
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   224
    if self.get_rqlexprs(action):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   225
        return True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   226
    if action in ('update', 'delete'):
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   227
        return 'owners' in self.get_groups(action)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   228
    return False
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   229
PermissionMixIn.has_local_role = has_local_role
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   230
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   231
def may_have_permission(self, action, req):
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   232
    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
   233
                                 self.has_perm(req, 'read')):
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   234
        return False
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   235
    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
   236
PermissionMixIn.may_have_permission = may_have_permission
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   237
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   238
def has_perm(self, session, action, **kwargs):
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   239
    """return true if the action is granted globaly or localy"""
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   240
    try:
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   241
        self.check_perm(session, action, **kwargs)
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   242
        return True
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   243
    except Unauthorized:
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   244
        return False
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   245
PermissionMixIn.has_perm = has_perm
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   246
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   247
def check_perm(self, session, action, **kwargs):
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   248
    # 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
   249
    # 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
   250
    # always stop there
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   251
    groups = self.get_groups(action)
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   252
    if session.user.matching_groups(groups):
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   253
        return
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   254
    # 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
   255
    # object, if so that's enough
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   256
    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
   257
        return
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   258
    # else if there is some rql expressions, check them
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   259
    if any(rqlexpr.check(session, **kwargs)
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   260
           for rqlexpr in self.get_rqlexprs(action)):
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   261
        return
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   262
    raise Unauthorized(action, str(self))
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   263
PermissionMixIn.check_perm = check_perm
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
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   266
RelationDefinitionSchema._RPROPERTIES['eid'] = None
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   267
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   268
def rql_expression(self, expression, mainvars=None, eid=None):
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   269
    """rql expression factory"""
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   270
    if self.rtype.final:
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   271
        return ERQLExpression(expression, mainvars, eid)
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   272
    return RRQLExpression(expression, mainvars, eid)
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   273
RelationDefinitionSchema.rql_expression = rql_expression
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   274
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   275
orig_check_permission_definitions = RelationDefinitionSchema.check_permission_definitions
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   276
def check_permission_definitions(self):
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   277
    orig_check_permission_definitions(self)
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   278
    schema = self.subject.schema
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   279
    for action, groups in self.permissions.iteritems():
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   280
        for group_or_rqlexpr in groups:
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   281
            if action == 'read' and \
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   282
                   isinstance(group_or_rqlexpr, RQLExpression):
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   283
                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
   284
                raise BadSchemaDefinition(msg % self)
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   285
            elif self.final and isinstance(group_or_rqlexpr, RRQLExpression):
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   286
                if schema.reading_from_database:
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   287
                    # we didn't have final relation earlier, so turn
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   288
                    # RRQLExpression into ERQLExpression now
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   289
                    rqlexpr = group_or_rqlexpr
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   290
                    newrqlexprs = [x for x in self.get_rqlexprs(action)
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   291
                                   if not x is rqlexpr]
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   292
                    newrqlexprs.append(ERQLExpression(rqlexpr.expression,
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   293
                                                      rqlexpr.mainvars,
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   294
                                                      rqlexpr.eid))
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   295
                    self.set_rqlexprs(action, newrqlexprs)
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   296
                else:
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   297
                    msg = "can't use RRQLExpression on %s, use an ERQLExpression"
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   298
                    raise BadSchemaDefinition(msg % self)
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   299
            elif not self.final and \
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   300
                     isinstance(group_or_rqlexpr, ERQLExpression):
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   301
                msg = "can't use ERQLExpression on %s, use a RRQLExpression"
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   302
                raise BadSchemaDefinition(msg % self)
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   303
RelationDefinitionSchema.check_permission_definitions = check_permission_definitions
0
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
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   306
class CubicWebEntitySchema(EntitySchema):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   307
    """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
   308
    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
   309
    constraints on those relations
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   310
    """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   311
    def __init__(self, schema=None, edef=None, eid=None, **kwargs):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   312
        super(CubicWebEntitySchema, self).__init__(schema, edef, **kwargs)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   313
        if eid is None and edef is not None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   314
            eid = getattr(edef, 'eid', None)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   315
        self.eid = eid
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   316
        # take care: no _groups attribute when deep-copying
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   317
        if getattr(self, 'permissions', None):
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   318
            for groups in self.permissions.itervalues():
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   319
                for group_or_rqlexpr in groups:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   320
                    if isinstance(group_or_rqlexpr, RRQLExpression):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   321
                        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
   322
                        raise BadSchemaDefinition(msg % self.type)
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   323
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   324
    def attribute_definitions(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   325
        """return an iterator on attribute definitions
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   326
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   327
        attribute relations are a subset of subject relations where the
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   328
        object's type is a final entity
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   329
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   330
        an attribute definition is a 2-uple :
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   331
        * name of the relation
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   332
        * schema of the destination entity type
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   333
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   334
        iter = super(CubicWebEntitySchema, self).attribute_definitions()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   335
        for rschema, attrschema in iter:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   336
            if rschema.type == 'has_text':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   337
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   338
            yield rschema, attrschema
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   339
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
   340
    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
   341
        """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
   342
        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
   343
        """
464edb198faa drop @ wildcard in relation subject/object, override main_attribute for proper behaviour
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2126
diff changeset
   344
        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
   345
            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
   346
                    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
   347
                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
   348
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   349
    def add_subject_relation(self, rschema):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   350
        """register the relation schema as possible subject relation"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   351
        super(CubicWebEntitySchema, self).add_subject_relation(rschema)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   352
        self._update_has_text()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   353
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   354
    def del_subject_relation(self, rtype):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   355
        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
   356
        self._update_has_text(True)
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   357
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
   358
    def _update_has_text(self, deletion=False):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   359
        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
   360
        need_has_text = None
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   361
        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
   362
            if rschema.final:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   363
                if rschema == 'has_text':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   364
                    has_has_text = True
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   365
                elif self.rdef(rschema).get('fulltextindexed'):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   366
                    may_need_has_text = True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   367
            elif rschema.fulltext_container:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   368
                if rschema.fulltext_container == 'subject':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   369
                    may_need_has_text = True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   370
                else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   371
                    need_has_text = False
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   372
        for rschema in self.object_relations():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   373
            if rschema.fulltext_container:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   374
                if rschema.fulltext_container == 'object':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   375
                    may_need_has_text = True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   376
                else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   377
                    need_has_text = False
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   378
        if need_has_text is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   379
            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
   380
        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
   381
            rdef = ybo.RelationDefinition(self.type, 'has_text', 'String')
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   382
            self.schema.add_relation_def(rdef)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   383
        elif not need_has_text and has_has_text:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   384
            self.schema.del_relation_def(self.type, 'has_text', 'String')
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   385
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   386
    def schema_entity(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   387
        """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
   388
        return self.type in SCHEMA_TYPES
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   389
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   390
    def rql_expression(self, expression, mainvars=None, eid=None):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   391
        """rql expression factory"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   392
        return ERQLExpression(expression, mainvars, eid)
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   393
2252
dd9758cb77e1 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2222
diff changeset
   394
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   395
class CubicWebRelationSchema(RelationSchema):
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   396
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   397
    def __init__(self, schema=None, rdef=None, eid=None, **kwargs):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   398
        if rdef is not None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   399
            # if this relation is inlined
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   400
            self.inlined = rdef.inlined
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   401
        super(CubicWebRelationSchema, self).__init__(schema, rdef, **kwargs)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   402
        if eid is None and rdef is not None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   403
            eid = getattr(rdef, 'eid', None)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   404
        self.eid = eid
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   405
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
   406
    @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
   407
    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
   408
        return self.type in META_RTYPES
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   409
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   410
    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
   411
        """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
   412
        return self.type in SCHEMA_TYPES
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   413
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   414
    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
   415
        if eschema is not None:
4019
7f68077d2c3b api update
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4005
diff changeset
   416
            for tschema in self.targets(eschema, role):
7f68077d2c3b api update
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4005
diff changeset
   417
                rdef = self.role_rdef(eschema, tschema, role)
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   418
                if rdef.may_have_permission(action, req):
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   419
                    return True
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   420
        else:
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   421
            for rdef in self.rdefs.itervalues():
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   422
                if rdef.may_have_permission(action, req):
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   423
                    return True
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   424
        return False
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   425
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   426
    def has_perm(self, session, action, **kwargs):
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   427
        """return true if the action is granted globaly or localy"""
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   428
        if 'fromeid' in kwargs:
4005
dee7af82beff should return item type not relation
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4004
diff changeset
   429
            subjtype = session.describe(kwargs['fromeid'])[0]
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   430
        else:
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   431
            subjtype = None
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   432
        if 'toeid' in kwargs:
4005
dee7af82beff should return item type not relation
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4004
diff changeset
   433
            objtype = session.describe(kwargs['toeid'])[0]
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   434
        else:
4037
42f3a80738d7 [mq]: typo
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4019
diff changeset
   435
            objtype = None
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   436
        if objtype and subjtype:
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   437
            return self.rdef(subjtype, objtype).has_perm(session, action, **kwargs)
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   438
        elif subjtype:
4004
c52619c738a5 api renaming update
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4003
diff changeset
   439
            for tschema in self.targets(subjtype, 'subject'):
c52619c738a5 api renaming update
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4003
diff changeset
   440
                rdef = self.rdef(subjtype, tschema)
4045
f4a52abb6f4f cw 3.6 api update
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4037
diff changeset
   441
                if not rdef.has_perm(session, action, **kwargs):
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   442
                    return False
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   443
        elif objtype:
4004
c52619c738a5 api renaming update
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4003
diff changeset
   444
            for tschema in self.targets(objtype, 'object'):
c52619c738a5 api renaming update
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4003
diff changeset
   445
                rdef = self.rdef(tschema, objtype)
c52619c738a5 api renaming update
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4003
diff changeset
   446
                if not rdef.has_perm(session, action, **kwargs):
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   447
                    return False
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   448
        else:
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   449
            for rdef in self.rdefs.itervalues():
4004
c52619c738a5 api renaming update
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4003
diff changeset
   450
                if not rdef.has_perm(session, action, **kwargs):
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   451
                    return False
4233
94ffaecd8e8c ouch, has_perm was always returning False...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4181
diff changeset
   452
        return True
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   453
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   454
    @deprecated('use .rdef(subjtype, objtype).role_cardinality(role)')
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   455
    def cardinality(self, subjtype, objtype, target):
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   456
        return self.rdef(subjtype, objtype).role_cardinality(target)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   457
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   458
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   459
class CubicWebSchema(Schema):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   460
    """set of entities and relations schema defining the possible data sets
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   461
    used in an application
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   462
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   463
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   464
    :type name: str
2476
1294a6bdf3bf application -> instance where it makes sense
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2460
diff changeset
   465
    :ivar name: name of the schema, usually the instance identifier
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   466
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   467
    :type base: str
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   468
    :ivar base: path of the directory where the schema is defined
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   469
    """
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   470
    reading_from_database = False
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   471
    entity_class = CubicWebEntitySchema
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   472
    relation_class = CubicWebRelationSchema
2958
44e5446b649b no inference for the identity relation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2926
diff changeset
   473
    no_specialization_inference = ('identity',)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   474
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   475
    def __init__(self, *args, **kwargs):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   476
        self._eid_index = {}
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   477
        super(CubicWebSchema, self).__init__(*args, **kwargs)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   478
        ybo.register_base_types(self)
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('eid'))
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('has_text'))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   482
        rschema.final = True
2300
c8151d004e06 meta has been drop
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2293
diff changeset
   483
        rschema = self.add_relation_type(ybo.RelationType('identity'))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   484
        rschema.final = False
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   485
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   486
    def add_entity_type(self, edef):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   487
        edef.name = edef.name.encode()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   488
        edef.name = bw_normalize_etype(edef.name)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   489
        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
   490
        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
   491
        if not eschema.final:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   492
            # automatically add the eid relation to non final entity types
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   493
            rdef = ybo.RelationDefinition(eschema.type, 'eid', 'Int',
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   494
                                          cardinality='11', uid=True)
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
            rdef = ybo.RelationDefinition(eschema.type, 'identity', eschema.type)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   497
            self.add_relation_def(rdef)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   498
        self._eid_index[eschema.eid] = eschema
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   499
        return eschema
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   500
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   501
    def add_relation_type(self, rdef):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   502
        rdef.name = rdef.name.lower().encode()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   503
        rschema = super(CubicWebSchema, self).add_relation_type(rdef)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   504
        self._eid_index[rschema.eid] = rschema
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   505
        return rschema
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   506
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   507
    def add_relation_def(self, rdef):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   508
        """build a part of a relation schema
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   509
        (i.e. add a relation between two specific entity's types)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   510
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   511
        :type subject: str
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   512
        :param subject: entity's type that is subject of the relation
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   513
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   514
        :type rtype: str
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   515
        :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
   516
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   517
        :type obj: str
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   518
        :param obj: entity's type that is object of the relation
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   519
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   520
        :rtype: RelationSchema
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   521
        :param: the newly created or just completed relation schema
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   522
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   523
        rdef.name = rdef.name.lower()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   524
        rdef.subject = bw_normalize_etype(rdef.subject)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   525
        rdef.object = bw_normalize_etype(rdef.object)
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   526
        rdefs = super(CubicWebSchema, self).add_relation_def(rdef)
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   527
        if rdefs:
1034
0356bbfb2f26 fix to pass arguments to base class
sylvain.thenault@logilab.fr
parents: 1016
diff changeset
   528
            try:
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   529
                self._eid_index[rdef.eid] = rdefs
1034
0356bbfb2f26 fix to pass arguments to base class
sylvain.thenault@logilab.fr
parents: 1016
diff changeset
   530
            except AttributeError:
0356bbfb2f26 fix to pass arguments to base class
sylvain.thenault@logilab.fr
parents: 1016
diff changeset
   531
                pass # not a serialized schema
4003
b9436fe77c9e fix bad merge
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 3998
diff changeset
   532
        return rdefs
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   533
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   534
    def del_relation_type(self, rtype):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   535
        rschema = self.rschema(rtype)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   536
        self._eid_index.pop(rschema.eid, None)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   537
        super(CubicWebSchema, self).del_relation_type(rtype)
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   538
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   539
    def del_relation_def(self, subjtype, rtype, objtype):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   540
        for k, v in self._eid_index.items():
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   541
            if not isinstance(v, RelationDefinitionSchema):
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   542
                continue
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   543
            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
   544
                del self._eid_index[k]
2718
3a56b87bb5d6 [schema] break when found
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2716
diff changeset
   545
                break
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   546
        super(CubicWebSchema, self).del_relation_def(subjtype, rtype, objtype)
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   547
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   548
    def del_entity_type(self, etype):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   549
        eschema = self.eschema(etype)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   550
        self._eid_index.pop(eschema.eid, None)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   551
        # deal with has_text first, else its automatic deletion (see above)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   552
        # may trigger an error in ancestor's del_entity_type method
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   553
        if 'has_text' in eschema.subject_relations():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   554
            self.del_relation_def(etype, 'has_text', 'String')
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   555
        super(CubicWebSchema, self).del_entity_type(etype)
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   556
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   557
    def schema_by_eid(self, eid):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   558
        return self._eid_index[eid]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   559
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   560
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   561
# Possible constraints ########################################################
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   562
3978
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   563
class BaseRQLConstraint(BaseConstraint):
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   564
    """base class for rql constraints
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   565
    """
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   566
3961
d1cbf77db999 fix RQLUniqueConstraint behaviour by using a DISTINCT query and allowing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   567
    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
   568
        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
   569
        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
   570
            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
   571
        else:
0d592677e55f nicer mainvars/expression handling when initializing rql constraints
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3961
diff changeset
   572
            normmainvars = []
0d592677e55f nicer mainvars/expression handling when initializing rql constraints
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3961
diff changeset
   573
            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
   574
                mainvar = mainvar.strip()
0d592677e55f nicer mainvars/expression handling when initializing rql constraints
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3961
diff changeset
   575
                if not mainvar.isalpha():
0d592677e55f nicer mainvars/expression handling when initializing rql constraints
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3961
diff changeset
   576
                    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
   577
                normmainvars.append(mainvar)
0d592677e55f nicer mainvars/expression handling when initializing rql constraints
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3961
diff changeset
   578
            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
   579
            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
   580
        self.mainvars = mainvars
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   581
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   582
    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
   583
        # 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
   584
        return ';' + self.mainvars + ';' + self.restriction
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   585
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   586
    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
   587
        # 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
   588
        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
   589
            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
   590
        _, 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
   591
        return cls(restriction, mainvars)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   592
    deserialize = classmethod(deserialize)
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   593
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   594
    def check(self, entity, rtype, value):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   595
        """return true if the value satisfy the constraint, else false"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   596
        # implemented as a hook in the repository
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   597
        return 1
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   598
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   599
    def repo_check(self, session, eidfrom, rtype, eidto):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   600
        """raise ValidationError if the relation doesn't satisfy the constraint
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   601
        """
3554
26e586f3c15c [schema] make RQL* constraints usable w/ attributes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3347
diff changeset
   602
        pass # this is a vocabulary constraint, not enforce XXX why?
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   603
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   604
    def __str__(self):
3965
94f95928f5ae nicer __str__ and __repr__ methods on rql constraints
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3964
diff changeset
   605
        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
   606
                                        self.restriction)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   607
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   608
    def __repr__(self):
3965
94f95928f5ae nicer __str__ and __repr__ methods on rql constraints
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3964
diff changeset
   609
        return '<%s @%#x>' % (self.__str__(), id(self))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   610
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   611
3978
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   612
class RQLVocabularyConstraint(BaseRQLConstraint):
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   613
    """the rql vocabulary constraint :
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   614
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   615
    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
   616
    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
   617
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   618
     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
   619
     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
   620
     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
   621
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   622
     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
   623
     `'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
   624
     done to guess it according to variable used in the expression.
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   625
    """
3978
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   626
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   627
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   628
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
   629
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
    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
   631
        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
   632
        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
   633
21387ffb0731 refactor so that we can specify an extra argument to constraints which
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3963
diff changeset
   634
    def serialize(self):
3968
e8dbad65a7a2 fix format string
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 3967
diff changeset
   635
        # start with a semicolon for bw compat, see below
e8dbad65a7a2 fix format string
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 3967
diff changeset
   636
        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
   637
                               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
   638
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
    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
   640
        # 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
   641
        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
   642
            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
   643
        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
   644
        _, 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
   645
        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
   646
    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
   647
3554
26e586f3c15c [schema] make RQL* constraints usable w/ attributes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3347
diff changeset
   648
    def repo_check(self, session, eidfrom, rtype, eidto=None):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   649
        """raise ValidationError if the relation doesn't satisfy the constraint
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   650
        """
3978
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   651
        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
   652
            # 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
   653
            # 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
   654
            # 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
   655
            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
   656
                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
   657
            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
   658
                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
   659
            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
   660
                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
   661
            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
   662
                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
   663
                    '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
   664
                    '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
   665
            raise ValidationError(maineid, {rtype: msg})
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   666
3978
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   667
    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
   668
        if eidto is None:
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   669
            # checking constraint for an attribute relation
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   670
            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
   671
            args, ck = {'s': eidfrom}, 's'
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   672
        else:
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   673
            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
   674
            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
   675
        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
   676
        if self.distinct_query:
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   677
            rql = 'DISTINCT ' + rql
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   678
        return session.unsafe_execute(rql, args, ck, build_descr=False)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   679
3978
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   680
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   681
class RQLConstraint(RepoEnforcedRQLConstraintMixIn, RQLVocabularyConstraint):
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   682
    """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
   683
    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
   684
    """
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   685
    distinct_query = False
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   686
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   687
    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
   688
        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
   689
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   690
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   691
class RQLUniqueConstraint(RepoEnforcedRQLConstraintMixIn, BaseRQLConstraint):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   692
    """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
   693
    greater than one
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   694
    """
3961
d1cbf77db999 fix RQLUniqueConstraint behaviour by using a DISTINCT query and allowing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   695
    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
   696
3985
d5bf894fcf02 add some notes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3980
diff changeset
   697
    # 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
   698
    #     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
   699
    #     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
   700
3978
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   701
    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
   702
        return len(self.exec_query(session, eidfrom, eidto)) <= 1
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   703
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   704
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   705
class RQLExpression(object):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   706
    def __init__(self, expression, mainvars, eid):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   707
        self.eid = eid # eid of the entity representing this rql expression
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   708
        if not isinstance(mainvars, unicode):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   709
            mainvars = unicode(mainvars)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   710
        self.mainvars = mainvars
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   711
        self.expression = normalize_expression(expression)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   712
        try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   713
            self.rqlst = parse(self.full_rql, print_errors=False).children[0]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   714
        except RQLSyntaxError:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   715
            raise RQLSyntaxError(expression)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   716
        for mainvar in mainvars.split(','):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   717
            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
   718
                _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
   719
                             'expression %s', mainvar, self)
3825
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3824
diff changeset
   720
        # 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
   721
        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
   722
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   723
    def __str__(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   724
        return self.full_rql
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   725
    def __repr__(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   726
        return '%s(%s)' % (self.__class__.__name__, self.full_rql)
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   727
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   728
    def __cmp__(self, other):
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   729
        if hasattr(other, 'expression'):
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   730
            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
   731
        return -1
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   732
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   733
    def __deepcopy__(self, memo):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   734
        return self.__class__(self.expression, self.mainvars)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   735
    def __getstate__(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   736
        return (self.expression, self.mainvars)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   737
    def __setstate__(self, state):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   738
        self.__init__(*state)
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   739
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   740
    @cached
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   741
    def transform_has_permission(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   742
        found = None
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   743
        rqlst = self.rqlst
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   744
        for var in rqlst.defined_vars.itervalues():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   745
            for varref in var.references():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   746
                rel = varref.relation()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   747
                if rel is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   748
                    continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   749
                try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   750
                    prefix, action, suffix = rel.r_type.split('_')
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   751
                except ValueError:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   752
                    continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   753
                if prefix != 'has' or suffix != 'permission' or \
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   754
                       not action in ('add', 'delete', 'update', 'read'):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   755
                    continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   756
                if found is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   757
                    found = []
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   758
                    rqlst.save_state()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   759
                assert rel.children[0].name == 'U'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   760
                objvar = rel.children[1].children[0].variable
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   761
                rqlst.remove_node(rel)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   762
                selected = [v.name for v in rqlst.get_selected_variables()]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   763
                if objvar.name not in selected:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   764
                    colindex = len(selected)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   765
                    rqlst.add_selected(objvar)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   766
                else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   767
                    colindex = selected.index(objvar.name)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   768
                found.append((action, objvar, colindex))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   769
                # 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
   770
                uvrefs = rqlst.defined_vars['U'].references()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   771
                if len(uvrefs) == 1:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   772
                    rqlst.remove_node(uvrefs[0].relation())
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   773
        if found is not None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   774
            rql = rqlst.as_string()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   775
            if len(rqlst.selection) == 1 and isinstance(rqlst.where, nodes.Relation):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   776
                # 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
   777
                keyarg = rqlst.selection[0].name.lower()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   778
            else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   779
                keyarg = None
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   780
            rqlst.recover()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   781
            return rql, found, keyarg
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   782
        return rqlst.as_string(), None, None
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   783
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   784
    def _check(self, session, **kwargs):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   785
        """return True if the rql expression is matching the given relation
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   786
        between fromeid and toeid
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
        session may actually be a request as well
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   789
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   790
        if self.eid is not None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   791
            key = (self.eid, tuple(sorted(kwargs.iteritems())))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   792
            try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   793
                return session.local_perm_cache[key]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   794
            except KeyError:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   795
                pass
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   796
        rql, has_perm_defs, keyarg = self.transform_has_permission()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   797
        if keyarg is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   798
            # on the server side, use unsafe_execute, but this is not available
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   799
            # on the client side (session is actually a request)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   800
            execute = getattr(session, 'unsafe_execute', session.execute)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   801
            # XXX what if 'u' in kwargs
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   802
            cachekey = kwargs.keys()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   803
            kwargs['u'] = session.user.eid
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   804
            try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   805
                rset = execute(rql, kwargs, cachekey, build_descr=True)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   806
            except NotImplementedError:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   807
                self.critical('cant check rql expression, unsupported rql %s', rql)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   808
                if self.eid is not None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   809
                    session.local_perm_cache[key] = False
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   810
                return False
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   811
            except TypeResolverException, ex:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   812
                # some expression may not be resolvable with current kwargs
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   813
                # (type conflict)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   814
                self.warning('%s: %s', rql, str(ex))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   815
                if self.eid is not None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   816
                    session.local_perm_cache[key] = False
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   817
                return False
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   818
        else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   819
            rset = session.eid_rset(kwargs[keyarg])
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   820
        # if no special has_*_permission relation in the rql expression, just
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   821
        # check the result set contains something
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   822
        if has_perm_defs is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   823
            if rset:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   824
                if self.eid is not None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   825
                    session.local_perm_cache[key] = True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   826
                return True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   827
        elif rset:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   828
            # check every special has_*_permission relation is satisfied
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   829
            get_eschema = session.vreg.schema.eschema
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   830
            try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   831
                for eaction, var, col in has_perm_defs:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   832
                    for i in xrange(len(rset)):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   833
                        eschema = get_eschema(rset.description[i][col])
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   834
                        eschema.check_perm(session, eaction, eid=rset[i][col])
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   835
                if self.eid is not None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   836
                    session.local_perm_cache[key] = True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   837
                return True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   838
            except Unauthorized:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   839
                pass
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   840
        if self.eid is not None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   841
            session.local_perm_cache[key] = False
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   842
        return False
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   843
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   844
    @property
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   845
    def minimal_rql(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   846
        return 'Any %s WHERE %s' % (self.mainvars, self.expression)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   847
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   848
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   849
class ERQLExpression(RQLExpression):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   850
    def __init__(self, expression, mainvars=None, eid=None):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   851
        RQLExpression.__init__(self, expression, mainvars or 'X', eid)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   852
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   853
    @property
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   854
    def full_rql(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   855
        rql = self.minimal_rql
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   856
        rqlst = getattr(self, 'rqlst', None) # may be not set yet
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   857
        if rqlst is not None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   858
            defined = rqlst.defined_vars
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   859
        else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   860
            defined = set(split_expression(self.expression))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   861
        if 'X' in defined:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   862
            rql += ', X eid %(x)s'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   863
        if 'U' in defined:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   864
            rql += ', U eid %(u)s'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   865
        return rql
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   866
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   867
    def check(self, session, eid=None):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   868
        if 'X' in self.rqlst.defined_vars:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   869
            if eid is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   870
                return False
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   871
            return self._check(session, x=eid)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   872
        return self._check(session)
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   873
3961
d1cbf77db999 fix RQLUniqueConstraint behaviour by using a DISTINCT query and allowing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   874
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   875
class RRQLExpression(RQLExpression):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   876
    def __init__(self, expression, mainvars=None, eid=None):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   877
        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
   878
            mainvars = guess_rrqlexpr_mainvars(expression)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   879
        RQLExpression.__init__(self, expression, mainvars, eid)
3827
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   880
        # 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
   881
        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
   882
        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
   883
            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
   884
                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
   885
                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
   886
            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
   887
                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
   888
            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
   889
                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
   890
                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
   891
                #self.vargraph[(lhsvarname, rhsvarname)] = relation.r_type
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   892
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   893
    @property
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   894
    def full_rql(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   895
        rql = self.minimal_rql
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   896
        rqlst = getattr(self, 'rqlst', None) # may be not set yet
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   897
        if rqlst is not None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   898
            defined = rqlst.defined_vars
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   899
        else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   900
            defined = set(split_expression(self.expression))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   901
        if 'S' in defined:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   902
            rql += ', S eid %(s)s'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   903
        if 'O' in defined:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   904
            rql += ', O eid %(o)s'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   905
        if 'U' in defined:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   906
            rql += ', U eid %(u)s'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   907
        return rql
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   908
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   909
    def check(self, session, fromeid=None, toeid=None):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   910
        kwargs = {}
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   911
        if 'S' in self.rqlst.defined_vars:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   912
            if fromeid is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   913
                return False
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   914
            kwargs['s'] = fromeid
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   915
        if 'O' in self.rqlst.defined_vars:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   916
            if toeid is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   917
                return False
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   918
            kwargs['o'] = toeid
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   919
        return self._check(session, **kwargs)
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   920
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   921
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
   922
# 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
   923
2460
ce1a7ffc6c90 fix a couple NameErrors
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2459
diff changeset
   924
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
   925
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
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
   927
    """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
   928
    (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
   929
    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
   930
    """
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
   931
    def __new__(mcs, name, bases, classdict):
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
   932
        abstract = classdict.pop('__abstract__', False)
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
   933
        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
   934
                                                          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
   935
        if not abstract:
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
   936
            make_workflowable(cls)
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
   937
        return cls
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
   938
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
   939
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
   940
    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
   941
    # 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
   942
    # cardinality, constraints and other relation definition properties
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
   943
    if 'custom_workflow' not in existing_rels:
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
   944
        rdef = ybo.SubjectRelation('Workflow')
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
   945
        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
   946
    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
   947
        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
   948
        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
   949
    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
   950
        rdef = ybo.ObjectRelation('TrInfo')
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
   951
        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
   952
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
   953
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
   954
    __metaclass__ = workflowable_definition
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
   955
    __abstract__ = True
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   956
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
   957
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   958
# schema loading ##############################################################
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   959
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   960
CONSTRAINTS['RQLConstraint'] = RQLConstraint
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   961
CONSTRAINTS['RQLUniqueConstraint'] = RQLUniqueConstraint
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   962
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
   963
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
   964
PyFileReader.context.update(CONSTRAINTS)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   965
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   966
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   967
class BootstrapSchemaLoader(SchemaLoader):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   968
    """cubicweb specific schema loader, loading only schema necessary to read
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   969
    the persistent schema
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   970
    """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   971
    schemacls = CubicWebSchema
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   972
1034
0356bbfb2f26 fix to pass arguments to base class
sylvain.thenault@logilab.fr
parents: 1016
diff changeset
   973
    def load(self, config, path=(), **kwargs):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   974
        """return a Schema instance from the schema definition read
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   975
        from <directory>
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   976
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   977
        return super(BootstrapSchemaLoader, self).load(
1034
0356bbfb2f26 fix to pass arguments to base class
sylvain.thenault@logilab.fr
parents: 1016
diff changeset
   978
            path, config.appid, register_base_types=False, **kwargs)
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   979
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   980
    def _load_definition_files(self, cubes=None):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   981
        # bootstraping, ignore cubes
2735
39c942241b48 no need for lib_directory
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2730
diff changeset
   982
        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
   983
        self.info('loading %s', filepath)
098aa2075903 include_schema_files is useless
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   984
        self.handle_file(filepath)
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   985
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   986
    def unhandled_file(self, filepath):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   987
        """called when a file without handler associated has been found"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   988
        self.warning('ignoring file %r', filepath)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   989
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   990
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   991
class CubicWebSchemaLoader(BootstrapSchemaLoader):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   992
    """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
   993
    instance's schema
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   994
    """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   995
1034
0356bbfb2f26 fix to pass arguments to base class
sylvain.thenault@logilab.fr
parents: 1016
diff changeset
   996
    def load(self, config, **kwargs):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   997
        """return a Schema instance from the schema definition read
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   998
        from <directory>
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   999
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1000
        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
  1001
        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
  1002
        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
  1003
            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
  1004
                self.extrapath[cubesdir] = 'cubes'
372
a8a975a88368 check apphome is not None
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 0
diff changeset
  1005
        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
  1006
            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
  1007
        else:
2598
a66fe74bd9fc [R schema] dont give an iterator, it's a trap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2596
diff changeset
  1008
            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
  1009
        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
  1010
            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
  1011
        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
  1012
            # 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
  1013
            cleanup_sys_modules([join(cubicweb.CW_SOFTWARE_ROOT, 'schemas')])
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1014
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1015
    def _load_definition_files(self, cubes):
2741
148d0cea1fb5 [schema] oops
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2736
diff changeset
  1016
        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
  1017
                         join(cubicweb.CW_SOFTWARE_ROOT, 'schemas', 'base.py'),
148d0cea1fb5 [schema] oops
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2736
diff changeset
  1018
                         join(cubicweb.CW_SOFTWARE_ROOT, 'schemas', 'workflow.py'),
148d0cea1fb5 [schema] oops
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2736
diff changeset
  1019
                         join(cubicweb.CW_SOFTWARE_ROOT, 'schemas', 'Bookmark.py')):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1020
            self.info('loading %s', filepath)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1021
            self.handle_file(filepath)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1022
        for cube in cubes:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1023
            for filepath in self.get_schema_files(cube):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1024
                self.info('loading %s', filepath)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1025
                self.handle_file(filepath)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1026
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1027
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
  1028
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
  1029
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
  1030
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
  1031
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1032
# _() 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
  1033
# translation
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1034
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
  1035
NEED_PERM_FORMATS = [_('text/cubicweb-page-template')]
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1036
2531
531ea4e7013e [cleanup] nicer imports
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2526
diff changeset
  1037
@monkeypatch(FormatConstraint)
3347
428f95118556 fix vocab param to avoid deprecation warning
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3287
diff changeset
  1038
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
  1039
    cw = None
3347
428f95118556 fix vocab param to avoid deprecation warning
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3287
diff changeset
  1040
    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
  1041
        cw = entity._cw
3347
428f95118556 fix vocab param to avoid deprecation warning
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3287
diff changeset
  1042
    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
  1043
        cw = form._cw
f893f4f199fc use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3369
diff changeset
  1044
    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
  1045
        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
  1046
    return self.regular_formats
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1047
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1048
# XXX monkey patch PyFileReader.import_erschema until bw_normalize_etype is
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1049
# necessary
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1050
orig_import_erschema = PyFileReader.import_erschema
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1051
def bw_import_erschema(self, ertype, schemamod=None, instantiate=True):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1052
    return orig_import_erschema(self, bw_normalize_etype(ertype), schemamod, instantiate)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1053
PyFileReader.import_erschema = bw_import_erschema
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
  1054
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1055
# XXX itou for some Statement methods
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1056
from rql import stmts
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1057
orig_get_etype = stmts.ScopeNode.get_etype
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1058
def bw_get_etype(self, name):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1059
    return orig_get_etype(self, bw_normalize_etype(name))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1060
stmts.ScopeNode.get_etype = bw_get_etype
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1061
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1062
orig_add_main_variable_delete = stmts.Delete.add_main_variable
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1063
def bw_add_main_variable_delete(self, etype, vref):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1064
    return orig_add_main_variable_delete(self, bw_normalize_etype(etype), vref)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1065
stmts.Delete.add_main_variable = bw_add_main_variable_delete
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1066
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1067
orig_add_main_variable_insert = stmts.Insert.add_main_variable
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1068
def bw_add_main_variable_insert(self, etype, vref):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1069
    return orig_add_main_variable_insert(self, bw_normalize_etype(etype), vref)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1070
stmts.Insert.add_main_variable = bw_add_main_variable_insert
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1071
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1072
orig_set_statement_type = stmts.Select.set_statement_type
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1073
def bw_set_statement_type(self, etype):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1074
    return orig_set_statement_type(self, bw_normalize_etype(etype))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1075
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
  1076
c5048502409f restore backward compat, still imported a lot
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2735
diff changeset
  1077
# XXX deprecated
3978
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
  1078
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