cubicweb/schema.py
author Sylvain Thénault <sylvain.thenault@logilab.fr>
Fri, 30 Sep 2016 18:25:08 +0200
changeset 11767 432f87a63057
parent 11765 9cb215e833b0
child 11775 39cf9e55ada8
permissions -rw-r--r--
flake8 and all * update some copyright * drop most __docformat__ declaration * fix some flake8 warnings / errors
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
11416
9c2fbb872e91 [schema] Add a method on yams constraints to compute its unique name
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11344
diff changeset
     1
# copyright 2003-2016 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
5421
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5122
diff changeset
     2
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5122
diff changeset
     3
#
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5122
diff changeset
     4
# This file is part of CubicWeb.
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5122
diff changeset
     5
#
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5122
diff changeset
     6
# CubicWeb is free software: you can redistribute it and/or modify it under the
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5122
diff changeset
     7
# terms of the GNU Lesser General Public License as published by the Free
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5122
diff changeset
     8
# Software Foundation, either version 2.1 of the License, or (at your option)
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5122
diff changeset
     9
# any later version.
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5122
diff changeset
    10
#
5424
8ecbcbff9777 replace logilab-common by CubicWeb in disclaimer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5421
diff changeset
    11
# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
5421
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5122
diff changeset
    12
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5122
diff changeset
    13
# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5122
diff changeset
    14
# details.
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5122
diff changeset
    15
#
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5122
diff changeset
    16
# You should have received a copy of the GNU Lesser General Public License along
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5122
diff changeset
    17
# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
6017
5f6a60ea8544 [relations in ui] provide context information when computing label for a relation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5896
diff changeset
    18
"""classes to define schemas for CubicWeb"""
11767
432f87a63057 flake8 and all
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11765
diff changeset
    19
10589
7c23b7de2b8d [py3k] print function
Samuel Trégouët <samuel.tregouet@logilab.fr>
parents: 10553
diff changeset
    20
from __future__ import print_function
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    21
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    22
import re
9366
bcbc92223b35 set proper PACKAGE information for yams 0.39
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9283
diff changeset
    23
from os.path import join, basename
11416
9c2fbb872e91 [schema] Add a method on yams constraints to compute its unique name
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11344
diff changeset
    24
from hashlib import md5
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    25
from logging import getLogger
1133
8a409ea0c9ec more linting
sylvain.thenault@logilab.fr
parents: 1132
diff changeset
    26
from warnings import warn
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    27
10791
22611236983d [schema] RQL queries are always unicode objects in python 3
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10689
diff changeset
    28
from six import PY2, text_type, string_types, add_metaclass
10609
e2d8e81bfe68 [py3k] import range using six.moves
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10589
diff changeset
    29
from six.moves import range
e2d8e81bfe68 [py3k] import range using six.moves
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10589
diff changeset
    30
9366
bcbc92223b35 set proper PACKAGE information for yams 0.39
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9283
diff changeset
    31
from logilab.common import tempattr
9280
bae0caa8477a [schema] edit syntax tree instead of playing with strings for RQLExpressions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9262
diff changeset
    32
from logilab.common.decorators import cached, clear_cache, monkeypatch, cachedproperty
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
    33
from logilab.common.logging_ext import set_log_methods
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
    34
from logilab.common.deprecation import deprecated
7152
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
    35
from logilab.common.textutils import splitstrip
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
    36
from logilab.common.graph import get_cycles
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    37
10553
1d824df4f2bd Fix (de)serialization of ComputedRelation read permissions
Julien Cristau <julien.cristau@logilab.fr>
parents: 10552
diff changeset
    38
import yams
2531
531ea4e7013e [cleanup] nicer imports
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2526
diff changeset
    39
from yams import BadSchemaDefinition, buildobjs as ybo
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
    40
from yams.schema import Schema, ERSchema, EntitySchema, RelationSchema, \
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
    41
    RelationDefinitionSchema, PermissionMixIn, role_name
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
    42
from yams.constraints import (BaseConstraint, FormatConstraint,
11215
4e79acdc36a6 [schema] use json to serialize constraints
Julien Cristau <julien.cristau@logilab.fr>
parents: 11151
diff changeset
    43
                              cstr_json_dumps, cstr_json_loads)
2531
531ea4e7013e [cleanup] nicer imports
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2526
diff changeset
    44
from yams.reader import (CONSTRAINTS, PyFileReader, SchemaLoader,
10517
fa9a0c80556d [schema] drop old backward compat code
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 10447
diff changeset
    45
                         cleanup_sys_modules, fill_schema_from_namespace)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    46
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    47
from rql import parse, nodes, RQLSyntaxError, TypeResolverException
9952
0f3f965b6365 [CWEP002] Add schema finalization checks for computed relations (rules)
Lea Capgen <lea.capgen@logilab.fr>, Sylvain Thénault <sylvain.thenault@logilab.fr>, Denis Laxalde <denis.laxalde@logilab.fr>
parents: 9951
diff changeset
    48
from rql.analyze import ETypeResolver
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    49
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
    50
import cubicweb
10666
7f6b5f023884 [py3k] replace '_ = unicode' in global scope (closes #7589459)
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10663
diff changeset
    51
from cubicweb import ETYPE_NAME_MAP, ValidationError, Unauthorized, _
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    52
11463
31e2de4d23a6 Drop bits from the past (no more dbapi isolated installation)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11446
diff changeset
    53
from cubicweb import server
9148
1b549c1acd4f [schema,server] add a security debugging aid (closes #2920304)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8945
diff changeset
    54
2596
d02eed70937f [R repo, schema] use VIRTUAL_RTYPES const
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2531
diff changeset
    55
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
    56
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
    57
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4843
diff changeset
    58
# 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
    59
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
    60
    'owned_by', 'created_by', 'is', 'is_instance_of', 'identity',
6427
c8a5ac2d1eaa [schema / sources] store data sources as cubicweb entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6377
diff changeset
    61
    'eid', 'creation_date', 'cw_source', 'modification_date', 'has_text', 'cwuri',
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
    62
))
6375
df4fd2a1b0e7 [schema] introduce new WORKFLOW_RTYPES set and use it to build SYSTEM_RTYPES/DONT_CHECK_RTYPES_ON_ADD/DONT_CHECK_RTYPES_ON_DEL sets
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6262
diff changeset
    63
WORKFLOW_RTYPES = set(('custom_workflow', 'in_state', 'wf_info_for'))
6377
3bb415310d4f [schema] introduce some new sets categorizing entity/relation types and benefits from them where possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6375
diff changeset
    64
WORKFLOW_DEF_RTYPES = set(('workflow_of', 'state_of', 'transition_of',
3bb415310d4f [schema] introduce some new sets categorizing entity/relation types and benefits from them where possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6375
diff changeset
    65
                           'initial_state', 'default_workflow',
3bb415310d4f [schema] introduce some new sets categorizing entity/relation types and benefits from them where possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6375
diff changeset
    66
                           'allowed_transition', 'destination_state',
3bb415310d4f [schema] introduce some new sets categorizing entity/relation types and benefits from them where possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6375
diff changeset
    67
                           'from_state', 'to_state', 'condition',
3bb415310d4f [schema] introduce some new sets categorizing entity/relation types and benefits from them where possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6375
diff changeset
    68
                           'subworkflow', 'subworkflow_state', 'subworkflow_exit',
9660
a78efec4cf04 Add missing relation types items in schema global variables
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 9635
diff changeset
    69
                           'by_transition',
6377
3bb415310d4f [schema] introduce some new sets categorizing entity/relation types and benefits from them where possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6375
diff changeset
    70
                           ))
7797
a71618a75b53 backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7782
diff changeset
    71
SYSTEM_RTYPES = set(('in_group', 'require_group',
6377
3bb415310d4f [schema] introduce some new sets categorizing entity/relation types and benefits from them where possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6375
diff changeset
    72
                     # cwproperty
3bb415310d4f [schema] introduce some new sets categorizing entity/relation types and benefits from them where possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6375
diff changeset
    73
                     'for_user',
9660
a78efec4cf04 Add missing relation types items in schema global variables
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 9635
diff changeset
    74
                     'cw_schema', 'cw_import_of', 'cw_for_source',
a78efec4cf04 Add missing relation types items in schema global variables
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 9635
diff changeset
    75
                     'cw_host_config_of',
6377
3bb415310d4f [schema] introduce some new sets categorizing entity/relation types and benefits from them where possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6375
diff changeset
    76
                     )) | WORKFLOW_RTYPES
6481
103774c8c215 [schema categorization] new NO_I18NCONTEXT set usable to somewhat control c-c i18n
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6427
diff changeset
    77
NO_I18NCONTEXT = META_RTYPES | WORKFLOW_RTYPES
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    78
6951
cb6314b09e0f [schema, ui] fix is_subobject to skip cw_source relation (else everything is considered as a subobject, since this relation is now composite)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6949
diff changeset
    79
SKIP_COMPOSITE_RELS = [('cw_source', 'subject')]
cb6314b09e0f [schema, ui] fix is_subobject to skip cw_source relation (else everything is considered as a subobject, since this relation is now composite)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6949
diff changeset
    80
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4843
diff changeset
    81
# set of entity and relation types 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
    82
SCHEMA_TYPES = set((
9974
b240b33c7125 [schema] CWComputedRType is a schema type
Julien Cristau <julien.cristau@logilab.fr>
parents: 9967
diff changeset
    83
    'CWEType', 'CWRType', 'CWComputedRType', 'CWAttribute', 'CWRelation',
6229
c4a70a5dd144 [schema] mark CWUniqueTogetherConstraint and its relations as schema entity/relations
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6191
diff changeset
    84
    'CWConstraint', 'CWConstraintType', 'CWUniqueTogetherConstraint',
c4a70a5dd144 [schema] mark CWUniqueTogetherConstraint and its relations as schema entity/relations
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6191
diff changeset
    85
    'RQLExpression',
6377
3bb415310d4f [schema] introduce some new sets categorizing entity/relation types and benefits from them where possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6375
diff changeset
    86
    'specializes',
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
    87
    '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
    88
    'constrained_by', 'cstrtype',
6229
c4a70a5dd144 [schema] mark CWUniqueTogetherConstraint and its relations as schema entity/relations
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6191
diff changeset
    89
    'constraint_of', 'relations',
6262
84901d735156 add permission relations to schema types
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6233
diff changeset
    90
    'read_permission', 'add_permission',
84901d735156 add permission relations to schema types
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6233
diff changeset
    91
    'delete_permission', 'update_permission',
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
    92
))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    93
4434
101344a6ff9b Improve the schema command with filtering option.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 4252
diff changeset
    94
WORKFLOW_TYPES = set(('Transition', 'State', 'TrInfo', 'Workflow',
4759
af2e6c377c71 cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4757
diff changeset
    95
                      'WorkflowTransition', 'BaseTransition',
af2e6c377c71 cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4757
diff changeset
    96
                      'SubWorkflowExitPoint'))
af2e6c377c71 cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4757
diff changeset
    97
9173
f3286e817f28 [schema] mark CWDataImport as an internal type. Closes #3025536
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9168
diff changeset
    98
INTERNAL_TYPES = set(('CWProperty', 'CWCache', 'ExternalUri', 'CWDataImport',
11681
b23d58050076 Merge cubicweb-pyramid cube
Yann Voté <yann.vote@logilab.fr>
parents: 11463
diff changeset
    99
                      'CWSource', 'CWSourceHostConfig', 'CWSourceSchemaConfig',
b23d58050076 Merge cubicweb-pyramid cube
Yann Voté <yann.vote@logilab.fr>
parents: 11463
diff changeset
   100
                      'CWSession'))
4434
101344a6ff9b Improve the schema command with filtering option.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 4252
diff changeset
   101
10813
ab626726a70a [syncschema] don't arbitrarily remove constraints from the in-memory schema
Julien Cristau <julien.cristau@logilab.fr>
parents: 10797
diff changeset
   102
UNIQUE_CONSTRAINTS = ('SizeConstraint', 'FormatConstraint',
ab626726a70a [syncschema] don't arbitrarily remove constraints from the in-memory schema
Julien Cristau <julien.cristau@logilab.fr>
parents: 10797
diff changeset
   103
                      'StaticVocabularyConstraint',
ab626726a70a [syncschema] don't arbitrarily remove constraints from the in-memory schema
Julien Cristau <julien.cristau@logilab.fr>
parents: 10797
diff changeset
   104
                      'RQLVocabularyConstraint')
4434
101344a6ff9b Improve the schema command with filtering option.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 4252
diff changeset
   105
2142
098aa2075903 include_schema_files is useless
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   106
_LOGGER = getLogger('cubicweb.schemaloader')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   107
8945
ba9e3fbfa5a5 [schemaserial] serialize additional yams parameter for customs type
Vincent Michel <vincent.michel@logilab.fr>
parents: 8892
diff changeset
   108
# entity and relation schema created from serialized schema have an eid
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   109
ybo.ETYPE_PROPERTIES += ('eid',)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   110
ybo.RTYPE_PROPERTIES += ('eid',)
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
   111
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   112
9951
8cdcbf3f4fd0 [schema] add utility function to build a CubicWebSchema from a namespace
Rémi Cardona <remi.cardona@logilab.fr>
parents: 9892
diff changeset
   113
def build_schema_from_namespace(items):
8cdcbf3f4fd0 [schema] add utility function to build a CubicWebSchema from a namespace
Rémi Cardona <remi.cardona@logilab.fr>
parents: 9892
diff changeset
   114
    schema = CubicWebSchema('noname')
8cdcbf3f4fd0 [schema] add utility function to build a CubicWebSchema from a namespace
Rémi Cardona <remi.cardona@logilab.fr>
parents: 9892
diff changeset
   115
    fill_schema_from_namespace(schema, items, register_base_types=False)
8cdcbf3f4fd0 [schema] add utility function to build a CubicWebSchema from a namespace
Rémi Cardona <remi.cardona@logilab.fr>
parents: 9892
diff changeset
   116
    return schema
8cdcbf3f4fd0 [schema] add utility function to build a CubicWebSchema from a namespace
Rémi Cardona <remi.cardona@logilab.fr>
parents: 9892
diff changeset
   117
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   118
9393
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   119
# Bases for manipulating RQL in schema #########################################
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   120
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   121
def guess_rrqlexpr_mainvars(expression):
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   122
    defined = set(split_expression(expression))
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   123
    mainvars = set()
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   124
    if 'S' in defined:
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   125
        mainvars.add('S')
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   126
    if 'O' in defined:
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   127
        mainvars.add('O')
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   128
    if 'U' in defined:
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   129
        mainvars.add('U')
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   130
    if not mainvars:
9957
5def1d98fce7 [schema] properly raise BadSchemaDefinition
Laura Médioni <laura.medioni@logilab.fr>
parents: 9952
diff changeset
   131
        raise BadSchemaDefinition('unable to guess selection variables in %r'
5def1d98fce7 [schema] properly raise BadSchemaDefinition
Laura Médioni <laura.medioni@logilab.fr>
parents: 9952
diff changeset
   132
                                  % expression)
9393
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   133
    return mainvars
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   134
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   135
9393
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   136
def split_expression(rqlstring):
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   137
    for expr in rqlstring.split(','):
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   138
        for noparen1 in expr.split('('):
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   139
            for noparen2 in noparen1.split(')'):
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   140
                for word in noparen2.split():
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   141
                    yield word
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   142
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   143
9393
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   144
def normalize_expression(rqlstring):
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   145
    """normalize an rql expression to ease schema synchronization (avoid
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   146
    suppressing and reinserting an expression if only a space has been
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   147
    added/removed for instance)
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   148
    """
10653
42c5bd7286b7 [schema] improve normalization of RQLExpressions
Julien Cristau <julien.cristau@logilab.fr>
parents: 10612
diff changeset
   149
    union = parse(u'Any 1 WHERE %s' % rqlstring).as_string()
10791
22611236983d [schema] RQL queries are always unicode objects in python 3
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10689
diff changeset
   150
    if PY2 and isinstance(union, str):
10653
42c5bd7286b7 [schema] improve normalization of RQLExpressions
Julien Cristau <julien.cristau@logilab.fr>
parents: 10612
diff changeset
   151
        union = union.decode('utf-8')
42c5bd7286b7 [schema] improve normalization of RQLExpressions
Julien Cristau <julien.cristau@logilab.fr>
parents: 10612
diff changeset
   152
    return union.split(' WHERE ', 1)[1]
9393
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   153
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   154
9967
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents: 9966
diff changeset
   155
def _check_valid_formula(rdef, formula_rqlst):
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents: 9966
diff changeset
   156
    """Check the formula is a valid RQL query with some restriction (no union,
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents: 9966
diff changeset
   157
    single selected node, etc.), raise BadSchemaDefinition if not
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents: 9966
diff changeset
   158
    """
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents: 9966
diff changeset
   159
    if len(formula_rqlst.children) != 1:
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents: 9966
diff changeset
   160
        raise BadSchemaDefinition('computed attribute %(attr)s on %(etype)s: '
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents: 9966
diff changeset
   161
                                  'can not use UNION in formula %(form)r' %
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   162
                                  {'attr': rdef.rtype,
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   163
                                   'etype': rdef.subject.type,
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   164
                                   'form': rdef.formula})
9967
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents: 9966
diff changeset
   165
    select = formula_rqlst.children[0]
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents: 9966
diff changeset
   166
    if len(select.selection) != 1:
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents: 9966
diff changeset
   167
        raise BadSchemaDefinition('computed attribute %(attr)s on %(etype)s: '
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents: 9966
diff changeset
   168
                                  'can only select one term in formula %(form)r' %
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   169
                                  {'attr': rdef.rtype,
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   170
                                   'etype': rdef.subject.type,
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   171
                                   'form': rdef.formula})
9967
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents: 9966
diff changeset
   172
    term = select.selection[0]
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents: 9966
diff changeset
   173
    types = set(term.get_type(sol) for sol in select.solutions)
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents: 9966
diff changeset
   174
    if len(types) != 1:
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents: 9966
diff changeset
   175
        raise BadSchemaDefinition('computed attribute %(attr)s on %(etype)s: '
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents: 9966
diff changeset
   176
                                  'multiple possible types (%(types)s) for formula %(form)r' %
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   177
                                  {'attr': rdef.rtype,
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   178
                                   'etype': rdef.subject.type,
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   179
                                   'types': list(types),
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   180
                                   'form': rdef.formula})
9967
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents: 9966
diff changeset
   181
    computed_type = types.pop()
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents: 9966
diff changeset
   182
    expected_type = rdef.object.type
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents: 9966
diff changeset
   183
    if computed_type != expected_type:
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents: 9966
diff changeset
   184
        raise BadSchemaDefinition('computed attribute %(attr)s on %(etype)s: '
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents: 9966
diff changeset
   185
                                  'computed attribute type (%(comp_type)s) mismatch with '
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents: 9966
diff changeset
   186
                                  'specified type (%(attr_type)s)' %
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   187
                                  {'attr': rdef.rtype,
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   188
                                   'etype': rdef.subject.type,
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   189
                                   'comp_type': computed_type,
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   190
                                   'attr_type': expected_type})
9967
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents: 9966
diff changeset
   191
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents: 9966
diff changeset
   192
9393
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   193
class RQLExpression(object):
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   194
    """Base class for RQL expression used in schema (constraints and
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   195
    permissions)
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   196
    """
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   197
    # these are overridden by set_log_methods below
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   198
    # only defining here to prevent pylint from complaining
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   199
    info = warning = error = critical = exception = debug = lambda msg, *a, **kw: None
9393
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   200
    # to be defined in concrete classes
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   201
    predefined_variables = None
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   202
11344
847ab4bdd985 [schema] Cache RQL expressions on schema loading
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 11343
diff changeset
   203
    # Internal cache for parsed expressions
847ab4bdd985 [schema] Cache RQL expressions on schema loading
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 11343
diff changeset
   204
    _rql_cache = {}
847ab4bdd985 [schema] Cache RQL expressions on schema loading
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 11343
diff changeset
   205
847ab4bdd985 [schema] Cache RQL expressions on schema loading
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 11343
diff changeset
   206
    @classmethod
847ab4bdd985 [schema] Cache RQL expressions on schema loading
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 11343
diff changeset
   207
    def _cached_parse(cls, rql):
847ab4bdd985 [schema] Cache RQL expressions on schema loading
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 11343
diff changeset
   208
        try:
847ab4bdd985 [schema] Cache RQL expressions on schema loading
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 11343
diff changeset
   209
            return cls._rql_cache[rql]
847ab4bdd985 [schema] Cache RQL expressions on schema loading
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 11343
diff changeset
   210
        except KeyError:
847ab4bdd985 [schema] Cache RQL expressions on schema loading
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 11343
diff changeset
   211
            cls._rql_cache[rql] = parse(rql, print_errors=False).children[0]
847ab4bdd985 [schema] Cache RQL expressions on schema loading
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 11343
diff changeset
   212
            return cls._rql_cache[rql]
847ab4bdd985 [schema] Cache RQL expressions on schema loading
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 11343
diff changeset
   213
9393
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   214
    def __init__(self, expression, mainvars, eid):
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   215
        """
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   216
        :type mainvars: sequence of RQL variables' names. Can be provided as a
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   217
                        comma separated string.
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   218
        :param mainvars: names of the variables being selected.
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   219
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   220
        """
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   221
        self.eid = eid  # eid of the entity representing this rql expression
9393
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   222
        assert mainvars, 'bad mainvars %s' % mainvars
10612
84468b90e9c1 [py3k] basestring → six.string_types
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10609
diff changeset
   223
        if isinstance(mainvars, string_types):
9393
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   224
            mainvars = set(splitstrip(mainvars))
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   225
        elif not isinstance(mainvars, set):
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   226
            mainvars = set(mainvars)
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   227
        self.mainvars = mainvars
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   228
        self.expression = normalize_expression(expression)
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   229
        try:
11343
892e4c12f03f [schema] Avoid parsing RQL expressions twice on schema loading
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 11215
diff changeset
   230
            # syntax tree used by read security (inserted in queries when necessary)
11344
847ab4bdd985 [schema] Cache RQL expressions on schema loading
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 11343
diff changeset
   231
            self.snippet_rqlst = self._cached_parse(self.minimal_rql)
9393
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   232
        except RQLSyntaxError:
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   233
            raise RQLSyntaxError(expression)
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   234
        for mainvar in mainvars:
11343
892e4c12f03f [schema] Avoid parsing RQL expressions twice on schema loading
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 11215
diff changeset
   235
            if len(self.snippet_rqlst.defined_vars[mainvar].references()) < 2:
9393
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   236
                _LOGGER.warn('You did not use the %s variable in your RQL '
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   237
                             'expression %s', mainvar, self)
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   238
        # graph of links between variables, used by rql rewriter
11343
892e4c12f03f [schema] Avoid parsing RQL expressions twice on schema loading
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 11215
diff changeset
   239
        self.vargraph = vargraph(self.snippet_rqlst)
9393
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   240
        # useful for some instrumentation, e.g. localperms permcheck command
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   241
        self.package = ybo.PACKAGE
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   242
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   243
    def __str__(self):
11343
892e4c12f03f [schema] Avoid parsing RQL expressions twice on schema loading
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 11215
diff changeset
   244
        return self.rqlst.as_string()
892e4c12f03f [schema] Avoid parsing RQL expressions twice on schema loading
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 11215
diff changeset
   245
9393
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   246
    def __repr__(self):
11343
892e4c12f03f [schema] Avoid parsing RQL expressions twice on schema loading
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 11215
diff changeset
   247
        return '%s(%s)' % (self.__class__.__name__, self.expression)
9393
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   248
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   249
    def __lt__(self, other):
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   250
        if hasattr(other, 'expression'):
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   251
            return self.expression < other.expression
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   252
        return True
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   253
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   254
    def __eq__(self, other):
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   255
        if hasattr(other, 'expression'):
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   256
            return self.expression == other.expression
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   257
        return False
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   258
10661
e6eb0c7c2e98 implement __ne__ whenever we implement __eq__
Julien Cristau <julien.cristau@logilab.fr>
parents: 10653
diff changeset
   259
    def __ne__(self, other):
e6eb0c7c2e98 implement __ne__ whenever we implement __eq__
Julien Cristau <julien.cristau@logilab.fr>
parents: 10653
diff changeset
   260
        return not (self == other)
e6eb0c7c2e98 implement __ne__ whenever we implement __eq__
Julien Cristau <julien.cristau@logilab.fr>
parents: 10653
diff changeset
   261
9393
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   262
    def __hash__(self):
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   263
        return hash(self.expression)
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   264
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   265
    def __deepcopy__(self, memo):
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   266
        return self.__class__(self.expression, self.mainvars)
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   267
9393
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   268
    def __getstate__(self):
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   269
        return (self.expression, self.mainvars)
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   270
9393
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   271
    def __setstate__(self, state):
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   272
        self.__init__(*state)
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   273
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   274
    @cachedproperty
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   275
    def rqlst(self):
11344
847ab4bdd985 [schema] Cache RQL expressions on schema loading
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 11343
diff changeset
   276
        # Don't use _cached_parse here because the rqlst is modified
9393
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   277
        select = parse(self.minimal_rql, print_errors=False).children[0]
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   278
        defined = set(split_expression(self.expression))
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   279
        for varname in self.predefined_variables:
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   280
            if varname in defined:
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   281
                select.add_eid_restriction(select.get_variable(varname), varname.lower(),
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   282
                                           'Substitute')
9393
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   283
        return select
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   284
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   285
    # permission rql expression specific stuff #################################
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   286
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   287
    @cached
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   288
    def transform_has_permission(self):
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   289
        found = None
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   290
        rqlst = self.rqlst
10663
54b8a1f249fb [py3k] dict.itervalues → dict.values
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10662
diff changeset
   291
        for var in rqlst.defined_vars.values():
9393
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   292
            for varref in var.references():
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   293
                rel = varref.relation()
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   294
                if rel is None:
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   295
                    continue
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   296
                try:
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   297
                    prefix, action, suffix = rel.r_type.split('_')
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   298
                except ValueError:
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   299
                    continue
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   300
                if (prefix != 'has' or suffix != 'permission' or
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   301
                        action not in ('add', 'delete', 'update', 'read')):
9393
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   302
                    continue
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   303
                if found is None:
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   304
                    found = []
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   305
                    rqlst.save_state()
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   306
                assert rel.children[0].name == 'U'
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   307
                objvar = rel.children[1].children[0].variable
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   308
                rqlst.remove_node(rel)
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   309
                selected = [v.name for v in rqlst.get_selected_variables()]
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   310
                if objvar.name not in selected:
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   311
                    colindex = len(selected)
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   312
                    rqlst.add_selected(objvar)
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   313
                else:
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   314
                    colindex = selected.index(objvar.name)
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   315
                found.append((action, colindex))
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   316
                # remove U eid %(u)s if U is not used in any other relation
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   317
                uvrefs = rqlst.defined_vars['U'].references()
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   318
                if len(uvrefs) == 1:
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   319
                    rqlst.remove_node(uvrefs[0].relation())
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   320
        if found is not None:
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   321
            rql = rqlst.as_string()
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   322
            if len(rqlst.selection) == 1 and isinstance(rqlst.where, nodes.Relation):
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   323
                # only "Any X WHERE X eid %(x)s" remaining, no need to execute the rql
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   324
                keyarg = rqlst.selection[0].name.lower()
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   325
            else:
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   326
                keyarg = None
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   327
            rqlst.recover()
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   328
            return rql, found, keyarg
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   329
        return rqlst.as_string(), None, None
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   330
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   331
    def _check(self, _cw, **kwargs):
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   332
        """return True if the rql expression is matching the given relation
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   333
        between fromeid and toeid
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   334
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   335
        _cw may be a request or a server side transaction
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   336
        """
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   337
        creating = kwargs.get('creating')
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   338
        if not creating and self.eid is not None:
10662
10942ed172de [py3k] dict.iteritems → dict.items
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10661
diff changeset
   339
            key = (self.eid, tuple(sorted(kwargs.items())))
9393
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   340
            try:
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   341
                return _cw.local_perm_cache[key]
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   342
            except KeyError:
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   343
                pass
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   344
        rql, has_perm_defs, keyarg = self.transform_has_permission()
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   345
        # when creating an entity, expression related to X satisfied
11343
892e4c12f03f [schema] Avoid parsing RQL expressions twice on schema loading
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 11215
diff changeset
   346
        if creating and 'X' in self.snippet_rqlst.defined_vars:
9393
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   347
            return True
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   348
        if keyarg is None:
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   349
            kwargs.setdefault('u', _cw.user.eid)
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   350
            try:
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   351
                rset = _cw.execute(rql, kwargs, build_descr=True)
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   352
            except NotImplementedError:
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   353
                self.critical('cant check rql expression, unsupported rql %s', rql)
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   354
                if self.eid is not None:
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   355
                    _cw.local_perm_cache[key] = False
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   356
                return False
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   357
            except TypeResolverException as ex:
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   358
                # some expression may not be resolvable with current kwargs
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   359
                # (type conflict)
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   360
                self.warning('%s: %s', rql, str(ex))
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   361
                if self.eid is not None:
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   362
                    _cw.local_perm_cache[key] = False
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   363
                return False
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   364
            except Unauthorized as ex:
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   365
                self.debug('unauthorized %s: %s', rql, str(ex))
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   366
                if self.eid is not None:
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   367
                    _cw.local_perm_cache[key] = False
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   368
                return False
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   369
        else:
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   370
            rset = _cw.eid_rset(kwargs[keyarg])
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   371
        # if no special has_*_permission relation in the rql expression, just
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   372
        # check the result set contains something
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   373
        if has_perm_defs is None:
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   374
            if rset:
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   375
                if self.eid is not None:
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   376
                    _cw.local_perm_cache[key] = True
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   377
                return True
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   378
        elif rset:
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   379
            # check every special has_*_permission relation is satisfied
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   380
            get_eschema = _cw.vreg.schema.eschema
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   381
            try:
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   382
                for eaction, col in has_perm_defs:
10609
e2d8e81bfe68 [py3k] import range using six.moves
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10589
diff changeset
   383
                    for i in range(len(rset)):
9393
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   384
                        eschema = get_eschema(rset.description[i][col])
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   385
                        eschema.check_perm(_cw, eaction, eid=rset[i][col])
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   386
                if self.eid is not None:
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   387
                    _cw.local_perm_cache[key] = True
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   388
                return True
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   389
            except Unauthorized:
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   390
                pass
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   391
        if self.eid is not None:
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   392
            _cw.local_perm_cache[key] = False
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   393
        return False
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   394
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   395
    @property
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   396
    def minimal_rql(self):
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   397
        return 'Any %s WHERE %s' % (','.join(sorted(self.mainvars)),
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   398
                                    self.expression)
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   399
9395
96dba2efd16d [hooks/security] provide attribute "add" permission
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9393
diff changeset
   400
9393
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   401
# rql expressions for use in permission definition #############################
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   402
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   403
class ERQLExpression(RQLExpression):
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   404
    predefined_variables = 'XU'
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   405
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   406
    def __init__(self, expression, mainvars=None, eid=None):
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   407
        RQLExpression.__init__(self, expression, mainvars or 'X', eid)
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   408
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   409
    def check(self, _cw, eid=None, creating=False, **kwargs):
11343
892e4c12f03f [schema] Avoid parsing RQL expressions twice on schema loading
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 11215
diff changeset
   410
        if 'X' in self.snippet_rqlst.defined_vars:
9393
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   411
            if eid is None:
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   412
                if creating:
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   413
                    return self._check(_cw, creating=True, **kwargs)
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   414
                return False
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   415
            assert not creating
9393
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   416
            return self._check(_cw, x=eid, **kwargs)
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   417
        return self._check(_cw, **kwargs)
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   418
10834
c9321aedfbf9 [schema] add CubicWebRelationDefinitionSchema
Julien Cristau <julien.cristau@logilab.fr>
parents: 10833
diff changeset
   419
c9321aedfbf9 [schema] add CubicWebRelationDefinitionSchema
Julien Cristau <julien.cristau@logilab.fr>
parents: 10833
diff changeset
   420
class CubicWebRelationDefinitionSchema(RelationDefinitionSchema):
c9321aedfbf9 [schema] add CubicWebRelationDefinitionSchema
Julien Cristau <julien.cristau@logilab.fr>
parents: 10833
diff changeset
   421
    def constraint_by_eid(self, eid):
c9321aedfbf9 [schema] add CubicWebRelationDefinitionSchema
Julien Cristau <julien.cristau@logilab.fr>
parents: 10833
diff changeset
   422
        for cstr in self.constraints:
c9321aedfbf9 [schema] add CubicWebRelationDefinitionSchema
Julien Cristau <julien.cristau@logilab.fr>
parents: 10833
diff changeset
   423
            if cstr.eid == eid:
c9321aedfbf9 [schema] add CubicWebRelationDefinitionSchema
Julien Cristau <julien.cristau@logilab.fr>
parents: 10833
diff changeset
   424
                return cstr
c9321aedfbf9 [schema] add CubicWebRelationDefinitionSchema
Julien Cristau <julien.cristau@logilab.fr>
parents: 10833
diff changeset
   425
        raise ValueError('No constraint with eid %d' % eid)
c9321aedfbf9 [schema] add CubicWebRelationDefinitionSchema
Julien Cristau <julien.cristau@logilab.fr>
parents: 10833
diff changeset
   426
c9321aedfbf9 [schema] add CubicWebRelationDefinitionSchema
Julien Cristau <julien.cristau@logilab.fr>
parents: 10833
diff changeset
   427
    def rql_expression(self, expression, mainvars=None, eid=None):
c9321aedfbf9 [schema] add CubicWebRelationDefinitionSchema
Julien Cristau <julien.cristau@logilab.fr>
parents: 10833
diff changeset
   428
        """rql expression factory"""
c9321aedfbf9 [schema] add CubicWebRelationDefinitionSchema
Julien Cristau <julien.cristau@logilab.fr>
parents: 10833
diff changeset
   429
        if self.rtype.final:
c9321aedfbf9 [schema] add CubicWebRelationDefinitionSchema
Julien Cristau <julien.cristau@logilab.fr>
parents: 10833
diff changeset
   430
            return ERQLExpression(expression, mainvars, eid)
c9321aedfbf9 [schema] add CubicWebRelationDefinitionSchema
Julien Cristau <julien.cristau@logilab.fr>
parents: 10833
diff changeset
   431
        return RRQLExpression(expression, mainvars, eid)
9600
bde625698f44 [merge] bring the 3.17.14 fixes to 3.18
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9395 9565
diff changeset
   432
10834
c9321aedfbf9 [schema] add CubicWebRelationDefinitionSchema
Julien Cristau <julien.cristau@logilab.fr>
parents: 10833
diff changeset
   433
    def check_permission_definitions(self):
c9321aedfbf9 [schema] add CubicWebRelationDefinitionSchema
Julien Cristau <julien.cristau@logilab.fr>
parents: 10833
diff changeset
   434
        super(CubicWebRelationDefinitionSchema, self).check_permission_definitions()
c9321aedfbf9 [schema] add CubicWebRelationDefinitionSchema
Julien Cristau <julien.cristau@logilab.fr>
parents: 10833
diff changeset
   435
        for action, groups in self.permissions.items():
c9321aedfbf9 [schema] add CubicWebRelationDefinitionSchema
Julien Cristau <julien.cristau@logilab.fr>
parents: 10833
diff changeset
   436
            for group_or_rqlexpr in groups:
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   437
                if action == 'read' and isinstance(group_or_rqlexpr, RQLExpression):
10834
c9321aedfbf9 [schema] add CubicWebRelationDefinitionSchema
Julien Cristau <julien.cristau@logilab.fr>
parents: 10833
diff changeset
   438
                    msg = "can't use rql expression for read permission of %s"
c9321aedfbf9 [schema] add CubicWebRelationDefinitionSchema
Julien Cristau <julien.cristau@logilab.fr>
parents: 10833
diff changeset
   439
                    raise BadSchemaDefinition(msg % self)
c9321aedfbf9 [schema] add CubicWebRelationDefinitionSchema
Julien Cristau <julien.cristau@logilab.fr>
parents: 10833
diff changeset
   440
                if self.final and isinstance(group_or_rqlexpr, RRQLExpression):
c9321aedfbf9 [schema] add CubicWebRelationDefinitionSchema
Julien Cristau <julien.cristau@logilab.fr>
parents: 10833
diff changeset
   441
                    msg = "can't use RRQLExpression on %s, use an ERQLExpression"
c9321aedfbf9 [schema] add CubicWebRelationDefinitionSchema
Julien Cristau <julien.cristau@logilab.fr>
parents: 10833
diff changeset
   442
                    raise BadSchemaDefinition(msg % self)
c9321aedfbf9 [schema] add CubicWebRelationDefinitionSchema
Julien Cristau <julien.cristau@logilab.fr>
parents: 10833
diff changeset
   443
                if not self.final and isinstance(group_or_rqlexpr, ERQLExpression):
c9321aedfbf9 [schema] add CubicWebRelationDefinitionSchema
Julien Cristau <julien.cristau@logilab.fr>
parents: 10833
diff changeset
   444
                    msg = "can't use ERQLExpression on %s, use a RRQLExpression"
c9321aedfbf9 [schema] add CubicWebRelationDefinitionSchema
Julien Cristau <julien.cristau@logilab.fr>
parents: 10833
diff changeset
   445
                    raise BadSchemaDefinition(msg % self)
9393
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   446
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   447
9393
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   448
def vargraph(rqlst):
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   449
    """ builds an adjacency graph of variables from the rql syntax tree, e.g:
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   450
    Any O,S WHERE T subworkflow_exit S, T subworkflow WF, O state_of WF
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   451
    => {'WF': ['O', 'T'], 'S': ['T'], 'T': ['WF', 'S'], 'O': ['WF']}
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   452
    """
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   453
    vargraph = {}
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   454
    for relation in rqlst.get_nodes(nodes.Relation):
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   455
        try:
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   456
            rhsvarname = relation.children[1].children[0].variable.name
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   457
            lhsvarname = relation.children[0].name
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   458
        except AttributeError:
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   459
            pass
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   460
        else:
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   461
            vargraph.setdefault(lhsvarname, []).append(rhsvarname)
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   462
            vargraph.setdefault(rhsvarname, []).append(lhsvarname)
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   463
    return vargraph
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   464
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   465
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   466
class GeneratedConstraint(object):
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   467
    def __init__(self, rqlst, mainvars):
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   468
        self.snippet_rqlst = rqlst
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   469
        self.mainvars = mainvars
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   470
        self.vargraph = vargraph(rqlst)
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   471
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   472
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   473
class RRQLExpression(RQLExpression):
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   474
    predefined_variables = 'SOU'
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   475
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   476
    def __init__(self, expression, mainvars=None, eid=None):
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   477
        if mainvars is None:
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   478
            mainvars = guess_rrqlexpr_mainvars(expression)
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   479
        RQLExpression.__init__(self, expression, mainvars, eid)
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   480
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   481
    def check(self, _cw, fromeid=None, toeid=None):
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   482
        kwargs = {}
11343
892e4c12f03f [schema] Avoid parsing RQL expressions twice on schema loading
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 11215
diff changeset
   483
        if 'S' in self.snippet_rqlst.defined_vars:
9393
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   484
            if fromeid is None:
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   485
                return False
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   486
            kwargs['s'] = fromeid
11343
892e4c12f03f [schema] Avoid parsing RQL expressions twice on schema loading
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 11215
diff changeset
   487
        if 'O' in self.snippet_rqlst.defined_vars:
9393
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   488
            if toeid is None:
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   489
                return False
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   490
            kwargs['o'] = toeid
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   491
        return self._check(_cw, **kwargs)
8266c8c375bb [schema] move definition of RQLExpression classes before default permission dicts
Julien Cristau <julien.cristau@logilab.fr>
parents: 9366
diff changeset
   492
9395
96dba2efd16d [hooks/security] provide attribute "add" permission
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9393
diff changeset
   493
96dba2efd16d [hooks/security] provide attribute "add" permission
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9393
diff changeset
   494
# In yams, default 'update' perm for attributes granted to managers and owners.
96dba2efd16d [hooks/security] provide attribute "add" permission
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9393
diff changeset
   495
# Within cw, we want to default to users who may edit the entity holding the
96dba2efd16d [hooks/security] provide attribute "add" permission
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9393
diff changeset
   496
# attribute.
96dba2efd16d [hooks/security] provide attribute "add" permission
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9393
diff changeset
   497
# These default permissions won't be checked by the security hooks:
96dba2efd16d [hooks/security] provide attribute "add" permission
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9393
diff changeset
   498
# since they delegate checking to the entity, we can skip actual checks.
96dba2efd16d [hooks/security] provide attribute "add" permission
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9393
diff changeset
   499
ybo.DEFAULT_ATTRPERMS['update'] = ('managers', ERQLExpression('U has_update_permission X'))
96dba2efd16d [hooks/security] provide attribute "add" permission
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9393
diff changeset
   500
ybo.DEFAULT_ATTRPERMS['add'] = ('managers', ERQLExpression('U has_add_permission X'))
96dba2efd16d [hooks/security] provide attribute "add" permission
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9393
diff changeset
   501
10553
1d824df4f2bd Fix (de)serialization of ComputedRelation read permissions
Julien Cristau <julien.cristau@logilab.fr>
parents: 10552
diff changeset
   502
# we don't want 'add' or 'delete' permissions on computed relation types
1d824df4f2bd Fix (de)serialization of ComputedRelation read permissions
Julien Cristau <julien.cristau@logilab.fr>
parents: 10552
diff changeset
   503
# (they're hardcoded to '()' on computed relation definitions)
1d824df4f2bd Fix (de)serialization of ComputedRelation read permissions
Julien Cristau <julien.cristau@logilab.fr>
parents: 10552
diff changeset
   504
if 'add' in yams.DEFAULT_COMPUTED_RELPERMS:
1d824df4f2bd Fix (de)serialization of ComputedRelation read permissions
Julien Cristau <julien.cristau@logilab.fr>
parents: 10552
diff changeset
   505
    del yams.DEFAULT_COMPUTED_RELPERMS['add']
1d824df4f2bd Fix (de)serialization of ComputedRelation read permissions
Julien Cristau <julien.cristau@logilab.fr>
parents: 10552
diff changeset
   506
if 'delete' in yams.DEFAULT_COMPUTED_RELPERMS:
1d824df4f2bd Fix (de)serialization of ComputedRelation read permissions
Julien Cristau <julien.cristau@logilab.fr>
parents: 10552
diff changeset
   507
    del yams.DEFAULT_COMPUTED_RELPERMS['delete']
1d824df4f2bd Fix (de)serialization of ComputedRelation read permissions
Julien Cristau <julien.cristau@logilab.fr>
parents: 10552
diff changeset
   508
9395
96dba2efd16d [hooks/security] provide attribute "add" permission
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9393
diff changeset
   509
4754
6bf17f810975 [schema] new constants for permissions definitions
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4717
diff changeset
   510
PUB_SYSTEM_ENTITY_PERMS = {
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   511
    'read': ('managers', 'users', 'guests',),
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   512
    'add': ('managers',),
4754
6bf17f810975 [schema] new constants for permissions definitions
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4717
diff changeset
   513
    'delete': ('managers',),
6bf17f810975 [schema] new constants for permissions definitions
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4717
diff changeset
   514
    'update': ('managers',),
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   515
}
4754
6bf17f810975 [schema] new constants for permissions definitions
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4717
diff changeset
   516
PUB_SYSTEM_REL_PERMS = {
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   517
    'read': ('managers', 'users', 'guests',),
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   518
    'add': ('managers',),
4754
6bf17f810975 [schema] new constants for permissions definitions
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4717
diff changeset
   519
    'delete': ('managers',),
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   520
}
4754
6bf17f810975 [schema] new constants for permissions definitions
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4717
diff changeset
   521
PUB_SYSTEM_ATTR_PERMS = {
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   522
    'read': ('managers', 'users', 'guests',),
9395
96dba2efd16d [hooks/security] provide attribute "add" permission
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9393
diff changeset
   523
    'add': ('managers',),
6944
0cf10429ad39 [sources] rewrite the way pyrorql mapping are stored in the database so it can be reused for other sources (eg datafeed+cwxml)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6861
diff changeset
   524
    'update': ('managers',),
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   525
}
4754
6bf17f810975 [schema] new constants for permissions definitions
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4717
diff changeset
   526
RO_REL_PERMS = {
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   527
    'read': ('managers', 'users', 'guests',),
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   528
    'add': (),
4754
6bf17f810975 [schema] new constants for permissions definitions
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4717
diff changeset
   529
    'delete': (),
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   530
}
4754
6bf17f810975 [schema] new constants for permissions definitions
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4717
diff changeset
   531
RO_ATTR_PERMS = {
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   532
    'read': ('managers', 'users', 'guests',),
9395
96dba2efd16d [hooks/security] provide attribute "add" permission
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9393
diff changeset
   533
    'add': ybo.DEFAULT_ATTRPERMS['add'],
4754
6bf17f810975 [schema] new constants for permissions definitions
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4717
diff changeset
   534
    'update': (),
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   535
}
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   536
4754
6bf17f810975 [schema] new constants for permissions definitions
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4717
diff changeset
   537
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
   538
# 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
   539
# 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
   540
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
   541
    """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
   542
    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
   543
    """
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
   544
    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
   545
    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
   546
        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
   547
            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
   548
        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
   549
            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
   550
    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
   551
    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
   552
        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
   553
        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
   554
                        % 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
   555
    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
   556
    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
   557
        # 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
   558
        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
   559
            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
   560
                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
   561
                del graph[eschema]
10663
54b8a1f249fb [py3k] dict.itervalues → dict.values
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10662
diff changeset
   562
                for deps in graph.values():
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
   563
                    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
   564
                        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
   565
                    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
   566
                        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
   567
    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
   568
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   569
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   570
def bw_normalize_etype(etype):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   571
    if etype in ETYPE_NAME_MAP:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   572
        msg = '%s has been renamed to %s, please update your code' % (
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   573
            etype, ETYPE_NAME_MAP[etype])
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   574
        warn(msg, DeprecationWarning, stacklevel=4)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   575
        etype = ETYPE_NAME_MAP[etype]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   576
    return etype
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   577
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   578
3275
5247789df541 [gettext] provide GNU contexts to avoid translations ambiguities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3240
diff changeset
   579
def display_name(req, key, form='', context=None):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   580
    """return a internationalized string for the key (schema entity or relation
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   581
    name) in a given form
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   582
    """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   583
    assert form in ('', 'plural', 'subject', 'object')
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   584
    if form == 'subject':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   585
        form = ''
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   586
    if form:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   587
        key = key + '_' + form
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   588
    # ensure unicode
3284
036cf5a25714 ensure pgettext return unicode as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3275
diff changeset
   589
    if context is not None:
10689
49a62b8f6d43 [py3k] unicode vs str vs bytes vs the world
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10674
diff changeset
   590
        return text_type(req.pgettext(context, key))
3275
5247789df541 [gettext] provide GNU contexts to avoid translations ambiguities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3240
diff changeset
   591
    else:
10689
49a62b8f6d43 [py3k] unicode vs str vs bytes vs the world
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10674
diff changeset
   592
        return text_type(req._(key))
3275
5247789df541 [gettext] provide GNU contexts to avoid translations ambiguities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3240
diff changeset
   593
3978
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   594
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   595
# Schema objects definition ###################################################
2c95e3033f64 finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3968
diff changeset
   596
3471
8c57c71b859c can now give context to rschema.display_name(...)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3401
diff changeset
   597
def ERSchema_display_name(self, req, form='', context=None):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   598
    """return a internationalized string for the entity/relation type name in
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   599
    a given form
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   600
    """
3471
8c57c71b859c can now give context to rschema.display_name(...)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3401
diff changeset
   601
    return display_name(req, self.type, form, context)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   602
ERSchema.display_name = ERSchema_display_name
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   603
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   604
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   605
@cached
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   606
def get_groups(self, action):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   607
    """return the groups authorized to perform <action> on entities of
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   608
    this type
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   609
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   610
    :type action: str
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   611
    :param action: the name of a permission
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   612
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   613
    :rtype: tuple
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   614
    :return: names of the groups with the given permission
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   615
    """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   616
    assert action in self.ACTIONS, action
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   617
    try:
10612
84468b90e9c1 [py3k] basestring → six.string_types
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10609
diff changeset
   618
        return frozenset(g for g in self.permissions[action] if isinstance(g, string_types))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   619
    except KeyError:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   620
        return ()
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   621
PermissionMixIn.get_groups = get_groups
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   622
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   623
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   624
@cached
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   625
def get_rqlexprs(self, action):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   626
    """return the rql expressions representing queries to check the user is allowed
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   627
    to perform <action> on entities of this type
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   628
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   629
    :type action: str
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   630
    :param action: the name of a permission
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   631
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   632
    :rtype: tuple
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   633
    :return: the rql expressions with the given permission
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   634
    """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   635
    assert action in self.ACTIONS, action
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   636
    try:
10612
84468b90e9c1 [py3k] basestring → six.string_types
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10609
diff changeset
   637
        return tuple(g for g in self.permissions[action] if not isinstance(g, string_types))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   638
    except KeyError:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   639
        return ()
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   640
PermissionMixIn.get_rqlexprs = get_rqlexprs
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   641
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   642
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   643
def set_action_permissions(self, action, permissions):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   644
    """set the groups and rql expressions allowing to perform <action> on
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   645
    entities of this type
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   646
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   647
    :type action: str
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   648
    :param action: the name of a permission
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   649
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   650
    :type permissions: tuple
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   651
    :param permissions: the groups and rql expressions allowing the given action
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   652
    """
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   653
    orig_set_action_permissions(self, action, tuple(permissions))
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   654
    clear_cache(self, 'get_rqlexprs')
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   655
    clear_cache(self, 'get_groups')
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   656
orig_set_action_permissions = PermissionMixIn.set_action_permissions
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   657
PermissionMixIn.set_action_permissions = set_action_permissions
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   658
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   659
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   660
def has_local_role(self, action):
10140
e14ec2aac099 [schema] Typo and indentation fix in RQLVocabularyConstraint doc string
Julien Cristau <julien.cristau@logilab.fr>
parents: 9990
diff changeset
   661
    """return true if the action *may* be granted locally (i.e. either rql
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   662
    expressions or the owners group are used in security definition)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   663
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   664
    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
   665
    'add' action checking. Also find a better name would be nice.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   666
    """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   667
    assert action in self.ACTIONS, action
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   668
    if self.get_rqlexprs(action):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   669
        return True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   670
    if action in ('update', 'delete'):
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   671
        return 'owners' in self.get_groups(action)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   672
    return False
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   673
PermissionMixIn.has_local_role = has_local_role
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   674
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   675
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   676
def may_have_permission(self, action, req):
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   677
    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
   678
                                 self.has_perm(req, 'read')):
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   679
        return False
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   680
    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
   681
PermissionMixIn.may_have_permission = may_have_permission
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   682
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   683
8540
fee98af8bb33 [schema] rename schema permissions function: session may also be a request, use _cw
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8258
diff changeset
   684
def has_perm(self, _cw, action, **kwargs):
9817
bb719d857421 [schema] spelling fixes in doc strings
Julien Cristau <julien.cristau@logilab.fr>
parents: 9711
diff changeset
   685
    """return true if the action is granted globally or locally"""
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   686
    try:
8540
fee98af8bb33 [schema] rename schema permissions function: session may also be a request, use _cw
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8258
diff changeset
   687
        self.check_perm(_cw, action, **kwargs)
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   688
        return True
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   689
    except Unauthorized:
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   690
        return False
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   691
PermissionMixIn.has_perm = has_perm
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   692
9148
1b549c1acd4f [schema,server] add a security debugging aid (closes #2920304)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8945
diff changeset
   693
8540
fee98af8bb33 [schema] rename schema permissions function: session may also be a request, use _cw
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8258
diff changeset
   694
def check_perm(self, _cw, action, **kwargs):
fee98af8bb33 [schema] rename schema permissions function: session may also be a request, use _cw
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8258
diff changeset
   695
    # NB: _cw may be a server transaction or a request object.
fee98af8bb33 [schema] rename schema permissions function: session may also be a request, use _cw
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8258
diff changeset
   696
    #
fee98af8bb33 [schema] rename schema permissions function: session may also be a request, use _cw
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8258
diff changeset
   697
    # check user is in an allowed group, if so that's enough internal
fee98af8bb33 [schema] rename schema permissions function: session may also be a request, use _cw
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8258
diff changeset
   698
    # transactions should always stop there
9148
1b549c1acd4f [schema,server] add a security debugging aid (closes #2920304)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8945
diff changeset
   699
    DBG = False
1b549c1acd4f [schema,server] add a security debugging aid (closes #2920304)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8945
diff changeset
   700
    if server.DEBUG & server.DBG_SEC:
1b549c1acd4f [schema,server] add a security debugging aid (closes #2920304)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8945
diff changeset
   701
        if action in server._SECURITY_CAPS:
1b549c1acd4f [schema,server] add a security debugging aid (closes #2920304)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8945
diff changeset
   702
            _self_str = str(self)
1b549c1acd4f [schema,server] add a security debugging aid (closes #2920304)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8945
diff changeset
   703
            if server._SECURITY_ITEMS:
1b549c1acd4f [schema,server] add a security debugging aid (closes #2920304)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8945
diff changeset
   704
                if any(item in _self_str for item in server._SECURITY_ITEMS):
1b549c1acd4f [schema,server] add a security debugging aid (closes #2920304)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8945
diff changeset
   705
                    DBG = True
1b549c1acd4f [schema,server] add a security debugging aid (closes #2920304)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8945
diff changeset
   706
            else:
1b549c1acd4f [schema,server] add a security debugging aid (closes #2920304)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8945
diff changeset
   707
                DBG = True
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   708
    groups = self.get_groups(action)
8540
fee98af8bb33 [schema] rename schema permissions function: session may also be a request, use _cw
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8258
diff changeset
   709
    if _cw.user.matching_groups(groups):
9148
1b549c1acd4f [schema,server] add a security debugging aid (closes #2920304)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8945
diff changeset
   710
        if DBG:
10589
7c23b7de2b8d [py3k] print function
Samuel Trégouët <samuel.tregouet@logilab.fr>
parents: 10553
diff changeset
   711
            print('check_perm: %r %r: user matches %s' % (action, _self_str, groups))
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   712
        return
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   713
    # 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
   714
    # object, if so that's enough
8540
fee98af8bb33 [schema] rename schema permissions function: session may also be a request, use _cw
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8258
diff changeset
   715
    #
fee98af8bb33 [schema] rename schema permissions function: session may also be a request, use _cw
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8258
diff changeset
   716
    # NB: give _cw to user.owns since user is not be bound to a transaction on
fee98af8bb33 [schema] rename schema permissions function: session may also be a request, use _cw
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8258
diff changeset
   717
    # the repository side
4607
55eab66c6592 [schema security] fix so that when cheking attributes perms for an entity being created, 'owners' and has_*_permission in erqlexpr are considered satisfied
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4586
diff changeset
   718
    if 'owners' in groups and (
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   719
            kwargs.get('creating')
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   720
            or ('eid' in kwargs and _cw.user.owns(kwargs['eid']))):
9148
1b549c1acd4f [schema,server] add a security debugging aid (closes #2920304)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8945
diff changeset
   721
        if DBG:
10589
7c23b7de2b8d [py3k] print function
Samuel Trégouët <samuel.tregouet@logilab.fr>
parents: 10553
diff changeset
   722
            print('check_perm: %r %r: user is owner or creation time' %
7c23b7de2b8d [py3k] print function
Samuel Trégouët <samuel.tregouet@logilab.fr>
parents: 10553
diff changeset
   723
                  (action, _self_str))
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   724
        return
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   725
    # else if there is some rql expressions, check them
9148
1b549c1acd4f [schema,server] add a security debugging aid (closes #2920304)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8945
diff changeset
   726
    if DBG:
10589
7c23b7de2b8d [py3k] print function
Samuel Trégouët <samuel.tregouet@logilab.fr>
parents: 10553
diff changeset
   727
        print('check_perm: %r %r %s' %
7c23b7de2b8d [py3k] print function
Samuel Trégouët <samuel.tregouet@logilab.fr>
parents: 10553
diff changeset
   728
              (action, _self_str, [(rqlexpr, kwargs, rqlexpr.check(_cw, **kwargs))
7c23b7de2b8d [py3k] print function
Samuel Trégouët <samuel.tregouet@logilab.fr>
parents: 10553
diff changeset
   729
                                   for rqlexpr in self.get_rqlexprs(action)]))
8540
fee98af8bb33 [schema] rename schema permissions function: session may also be a request, use _cw
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8258
diff changeset
   730
    if any(rqlexpr.check(_cw, **kwargs)
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   731
           for rqlexpr in self.get_rqlexprs(action)):
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   732
        return
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   733
    raise Unauthorized(action, str(self))
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   734
PermissionMixIn.check_perm = check_perm
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   735
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   736
10834
c9321aedfbf9 [schema] add CubicWebRelationDefinitionSchema
Julien Cristau <julien.cristau@logilab.fr>
parents: 10833
diff changeset
   737
CubicWebRelationDefinitionSchema._RPROPERTIES['eid'] = None
8945
ba9e3fbfa5a5 [schemaserial] serialize additional yams parameter for customs type
Vincent Michel <vincent.michel@logilab.fr>
parents: 8892
diff changeset
   738
# remember rproperties defined at this point. Others will have to be serialized in
ba9e3fbfa5a5 [schemaserial] serialize additional yams parameter for customs type
Vincent Michel <vincent.michel@logilab.fr>
parents: 8892
diff changeset
   739
# CWAttribute.extra_props
10834
c9321aedfbf9 [schema] add CubicWebRelationDefinitionSchema
Julien Cristau <julien.cristau@logilab.fr>
parents: 10833
diff changeset
   740
KNOWN_RPROPERTIES = CubicWebRelationDefinitionSchema.ALL_PROPERTIES()
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   741
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   742
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   743
class CubicWebEntitySchema(EntitySchema):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   744
    """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
   745
    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
   746
    constraints on those relations
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   747
    """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   748
    def __init__(self, schema=None, edef=None, eid=None, **kwargs):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   749
        super(CubicWebEntitySchema, self).__init__(schema, edef, **kwargs)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   750
        if eid is None and edef is not None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   751
            eid = getattr(edef, 'eid', None)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   752
        self.eid = eid
4574
2380444d982c [schema] refactor/cleanup check_permissions
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4570
diff changeset
   753
9547
43aace16a953 [schema] add composite handling helpers on EntitySchema (related to #3463112)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9469
diff changeset
   754
    def targets(self, role):
43aace16a953 [schema] add composite handling helpers on EntitySchema (related to #3463112)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9469
diff changeset
   755
        assert role in ('subject', 'object')
43aace16a953 [schema] add composite handling helpers on EntitySchema (related to #3463112)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9469
diff changeset
   756
        if role == 'subject':
43aace16a953 [schema] add composite handling helpers on EntitySchema (related to #3463112)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9469
diff changeset
   757
            return self.subjrels.values()
43aace16a953 [schema] add composite handling helpers on EntitySchema (related to #3463112)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9469
diff changeset
   758
        return self.objrels.values()
43aace16a953 [schema] add composite handling helpers on EntitySchema (related to #3463112)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9469
diff changeset
   759
43aace16a953 [schema] add composite handling helpers on EntitySchema (related to #3463112)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9469
diff changeset
   760
    @cachedproperty
43aace16a953 [schema] add composite handling helpers on EntitySchema (related to #3463112)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9469
diff changeset
   761
    def composite_rdef_roles(self):
43aace16a953 [schema] add composite handling helpers on EntitySchema (related to #3463112)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9469
diff changeset
   762
        """Return all relation definitions that define the current entity
43aace16a953 [schema] add composite handling helpers on EntitySchema (related to #3463112)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9469
diff changeset
   763
        type as a composite.
43aace16a953 [schema] add composite handling helpers on EntitySchema (related to #3463112)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9469
diff changeset
   764
        """
43aace16a953 [schema] add composite handling helpers on EntitySchema (related to #3463112)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9469
diff changeset
   765
        rdef_roles = []
43aace16a953 [schema] add composite handling helpers on EntitySchema (related to #3463112)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9469
diff changeset
   766
        for role in ('subject', 'object'):
43aace16a953 [schema] add composite handling helpers on EntitySchema (related to #3463112)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9469
diff changeset
   767
            for rschema in self.targets(role):
43aace16a953 [schema] add composite handling helpers on EntitySchema (related to #3463112)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9469
diff changeset
   768
                if rschema.final:
43aace16a953 [schema] add composite handling helpers on EntitySchema (related to #3463112)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9469
diff changeset
   769
                    continue
43aace16a953 [schema] add composite handling helpers on EntitySchema (related to #3463112)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9469
diff changeset
   770
                for rdef in rschema.rdefs.values():
9711
59616edc20d7 [schema] fix buggy composite_rdef_roles and associated test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9660
diff changeset
   771
                    if (role == 'subject' and rdef.subject == self) or \
59616edc20d7 [schema] fix buggy composite_rdef_roles and associated test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9660
diff changeset
   772
                            (role == 'object' and rdef.object == self):
59616edc20d7 [schema] fix buggy composite_rdef_roles and associated test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9660
diff changeset
   773
                        crole = rdef.composite
59616edc20d7 [schema] fix buggy composite_rdef_roles and associated test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9660
diff changeset
   774
                        if crole == role:
59616edc20d7 [schema] fix buggy composite_rdef_roles and associated test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9660
diff changeset
   775
                            rdef_roles.append((rdef, role))
9547
43aace16a953 [schema] add composite handling helpers on EntitySchema (related to #3463112)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9469
diff changeset
   776
        return rdef_roles
43aace16a953 [schema] add composite handling helpers on EntitySchema (related to #3463112)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9469
diff changeset
   777
43aace16a953 [schema] add composite handling helpers on EntitySchema (related to #3463112)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9469
diff changeset
   778
    @cachedproperty
43aace16a953 [schema] add composite handling helpers on EntitySchema (related to #3463112)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9469
diff changeset
   779
    def is_composite(self):
43aace16a953 [schema] add composite handling helpers on EntitySchema (related to #3463112)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9469
diff changeset
   780
        return bool(len(self.composite_rdef_roles))
43aace16a953 [schema] add composite handling helpers on EntitySchema (related to #3463112)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9469
diff changeset
   781
4574
2380444d982c [schema] refactor/cleanup check_permissions
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4570
diff changeset
   782
    def check_permission_definitions(self):
2380444d982c [schema] refactor/cleanup check_permissions
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4570
diff changeset
   783
        super(CubicWebEntitySchema, self).check_permission_definitions()
10663
54b8a1f249fb [py3k] dict.itervalues → dict.values
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10662
diff changeset
   784
        for groups in self.permissions.values():
4574
2380444d982c [schema] refactor/cleanup check_permissions
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4570
diff changeset
   785
            for group_or_rqlexpr in groups:
2380444d982c [schema] refactor/cleanup check_permissions
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4570
diff changeset
   786
                if isinstance(group_or_rqlexpr, RRQLExpression):
2380444d982c [schema] refactor/cleanup check_permissions
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4570
diff changeset
   787
                    msg = "can't use RRQLExpression on %s, use an ERQLExpression"
2380444d982c [schema] refactor/cleanup check_permissions
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4570
diff changeset
   788
                    raise BadSchemaDefinition(msg % self.type)
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   789
6951
cb6314b09e0f [schema, ui] fix is_subobject to skip cw_source relation (else everything is considered as a subobject, since this relation is now composite)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6949
diff changeset
   790
    def is_subobject(self, strict=False, skiprels=None):
cb6314b09e0f [schema, ui] fix is_subobject to skip cw_source relation (else everything is considered as a subobject, since this relation is now composite)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6949
diff changeset
   791
        if skiprels is None:
cb6314b09e0f [schema, ui] fix is_subobject to skip cw_source relation (else everything is considered as a subobject, since this relation is now composite)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6949
diff changeset
   792
            skiprels = SKIP_COMPOSITE_RELS
cb6314b09e0f [schema, ui] fix is_subobject to skip cw_source relation (else everything is considered as a subobject, since this relation is now composite)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6949
diff changeset
   793
        else:
cb6314b09e0f [schema, ui] fix is_subobject to skip cw_source relation (else everything is considered as a subobject, since this relation is now composite)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6949
diff changeset
   794
            skiprels += SKIP_COMPOSITE_RELS
cb6314b09e0f [schema, ui] fix is_subobject to skip cw_source relation (else everything is considered as a subobject, since this relation is now composite)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6949
diff changeset
   795
        return super(CubicWebEntitySchema, self).is_subobject(strict,
cb6314b09e0f [schema, ui] fix is_subobject to skip cw_source relation (else everything is considered as a subobject, since this relation is now composite)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6949
diff changeset
   796
                                                              skiprels=skiprels)
cb6314b09e0f [schema, ui] fix is_subobject to skip cw_source relation (else everything is considered as a subobject, since this relation is now composite)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6949
diff changeset
   797
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   798
    def attribute_definitions(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   799
        """return an iterator on attribute definitions
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   800
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   801
        attribute relations are a subset of subject relations where the
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   802
        object's type is a final entity
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   803
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   804
        an attribute definition is a 2-uple :
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   805
        * name of the relation
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   806
        * schema of the destination entity type
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   807
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   808
        iter = super(CubicWebEntitySchema, self).attribute_definitions()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   809
        for rschema, attrschema in iter:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   810
            if rschema.type == 'has_text':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   811
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   812
            yield rschema, attrschema
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   813
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
   814
    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
   815
        """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
   816
        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
   817
        """
464edb198faa drop @ wildcard in relation subject/object, override main_attribute for proper behaviour
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2126
diff changeset
   818
        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
   819
            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
   820
                    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
   821
                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
   822
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   823
    def add_subject_relation(self, rschema):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   824
        """register the relation schema as possible subject relation"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   825
        super(CubicWebEntitySchema, self).add_subject_relation(rschema)
7467
5a6b3e51807d [schema] fix computing of has_text relation: when a fulltext_container relation is added, we need to recompute has_text for the target entity type as well. Also, avoid computation when not needed
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7152
diff changeset
   826
        if rschema.final:
5a6b3e51807d [schema] fix computing of has_text relation: when a fulltext_container relation is added, we need to recompute has_text for the target entity type as well. Also, avoid computation when not needed
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7152
diff changeset
   827
            if self.rdef(rschema).get('fulltextindexed'):
5a6b3e51807d [schema] fix computing of has_text relation: when a fulltext_container relation is added, we need to recompute has_text for the target entity type as well. Also, avoid computation when not needed
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7152
diff changeset
   828
                self._update_has_text()
5a6b3e51807d [schema] fix computing of has_text relation: when a fulltext_container relation is added, we need to recompute has_text for the target entity type as well. Also, avoid computation when not needed
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7152
diff changeset
   829
        elif rschema.fulltext_container:
5a6b3e51807d [schema] fix computing of has_text relation: when a fulltext_container relation is added, we need to recompute has_text for the target entity type as well. Also, avoid computation when not needed
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7152
diff changeset
   830
            self._update_has_text()
5a6b3e51807d [schema] fix computing of has_text relation: when a fulltext_container relation is added, we need to recompute has_text for the target entity type as well. Also, avoid computation when not needed
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7152
diff changeset
   831
5a6b3e51807d [schema] fix computing of has_text relation: when a fulltext_container relation is added, we need to recompute has_text for the target entity type as well. Also, avoid computation when not needed
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7152
diff changeset
   832
    def add_object_relation(self, rschema):
5a6b3e51807d [schema] fix computing of has_text relation: when a fulltext_container relation is added, we need to recompute has_text for the target entity type as well. Also, avoid computation when not needed
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7152
diff changeset
   833
        """register the relation schema as possible object relation"""
5a6b3e51807d [schema] fix computing of has_text relation: when a fulltext_container relation is added, we need to recompute has_text for the target entity type as well. Also, avoid computation when not needed
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7152
diff changeset
   834
        super(CubicWebEntitySchema, self).add_object_relation(rschema)
5a6b3e51807d [schema] fix computing of has_text relation: when a fulltext_container relation is added, we need to recompute has_text for the target entity type as well. Also, avoid computation when not needed
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7152
diff changeset
   835
        if rschema.fulltext_container:
5a6b3e51807d [schema] fix computing of has_text relation: when a fulltext_container relation is added, we need to recompute has_text for the target entity type as well. Also, avoid computation when not needed
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7152
diff changeset
   836
            self._update_has_text()
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   837
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   838
    def del_subject_relation(self, rtype):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   839
        super(CubicWebEntitySchema, self).del_subject_relation(rtype)
7467
5a6b3e51807d [schema] fix computing of has_text relation: when a fulltext_container relation is added, we need to recompute has_text for the target entity type as well. Also, avoid computation when not needed
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7152
diff changeset
   840
        if 'has_text' in self.subjrels:
5a6b3e51807d [schema] fix computing of has_text relation: when a fulltext_container relation is added, we need to recompute has_text for the target entity type as well. Also, avoid computation when not needed
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7152
diff changeset
   841
            self._update_has_text(deletion=True)
5a6b3e51807d [schema] fix computing of has_text relation: when a fulltext_container relation is added, we need to recompute has_text for the target entity type as well. Also, avoid computation when not needed
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7152
diff changeset
   842
5a6b3e51807d [schema] fix computing of has_text relation: when a fulltext_container relation is added, we need to recompute has_text for the target entity type as well. Also, avoid computation when not needed
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7152
diff changeset
   843
    def del_object_relation(self, rtype):
5a6b3e51807d [schema] fix computing of has_text relation: when a fulltext_container relation is added, we need to recompute has_text for the target entity type as well. Also, avoid computation when not needed
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7152
diff changeset
   844
        super(CubicWebEntitySchema, self).del_object_relation(rtype)
5a6b3e51807d [schema] fix computing of has_text relation: when a fulltext_container relation is added, we need to recompute has_text for the target entity type as well. Also, avoid computation when not needed
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7152
diff changeset
   845
        if 'has_text' in self.subjrels:
5a6b3e51807d [schema] fix computing of has_text relation: when a fulltext_container relation is added, we need to recompute has_text for the target entity type as well. Also, avoid computation when not needed
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7152
diff changeset
   846
            self._update_has_text(deletion=True)
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   847
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
   848
    def _update_has_text(self, deletion=False):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   849
        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
   850
        need_has_text = None
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   851
        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
   852
            if rschema.final:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   853
                if rschema == 'has_text':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   854
                    has_has_text = True
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   855
                elif self.rdef(rschema).get('fulltextindexed'):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   856
                    may_need_has_text = True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   857
            elif rschema.fulltext_container:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   858
                if rschema.fulltext_container == 'subject':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   859
                    may_need_has_text = True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   860
                else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   861
                    need_has_text = False
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   862
        for rschema in self.object_relations():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   863
            if rschema.fulltext_container:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   864
                if rschema.fulltext_container == 'object':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   865
                    may_need_has_text = True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   866
                else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   867
                    need_has_text = False
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   868
        if need_has_text is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   869
            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
   870
        if need_has_text and not has_has_text and not deletion:
4755
13a5d3a7410e [schema] tweaks meta-relations and schema/workflow entities attributes permissions
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4754
diff changeset
   871
            rdef = ybo.RelationDefinition(self.type, 'has_text', 'String',
13a5d3a7410e [schema] tweaks meta-relations and schema/workflow entities attributes permissions
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4754
diff changeset
   872
                                          __permissions__=RO_ATTR_PERMS)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   873
            self.schema.add_relation_def(rdef)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   874
        elif not need_has_text and has_has_text:
5122
c06078d59e87 [schema] ensure we don't remove has_text relation type unfortunatly
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5030
diff changeset
   875
            # use rschema.del_relation_def and not schema.del_relation_def to
c06078d59e87 [schema] ensure we don't remove has_text relation type unfortunatly
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5030
diff changeset
   876
            # avoid deleting the relation type accidentally...
c06078d59e87 [schema] ensure we don't remove has_text relation type unfortunatly
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5030
diff changeset
   877
            self.schema['has_text'].del_relation_def(self, self.schema['String'])
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   878
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   879
    def schema_entity(self):  # XXX @property for consistency with meta
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   880
        """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
   881
        return self.type in SCHEMA_TYPES
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   882
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   883
    def rql_expression(self, expression, mainvars=None, eid=None):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   884
        """rql expression factory"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   885
        return ERQLExpression(expression, mainvars, eid)
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   886
2252
dd9758cb77e1 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2222
diff changeset
   887
10553
1d824df4f2bd Fix (de)serialization of ComputedRelation read permissions
Julien Cristau <julien.cristau@logilab.fr>
parents: 10552
diff changeset
   888
class CubicWebRelationSchema(PermissionMixIn, RelationSchema):
1d824df4f2bd Fix (de)serialization of ComputedRelation read permissions
Julien Cristau <julien.cristau@logilab.fr>
parents: 10552
diff changeset
   889
    permissions = {}
1d824df4f2bd Fix (de)serialization of ComputedRelation read permissions
Julien Cristau <julien.cristau@logilab.fr>
parents: 10552
diff changeset
   890
    ACTIONS = ()
10834
c9321aedfbf9 [schema] add CubicWebRelationDefinitionSchema
Julien Cristau <julien.cristau@logilab.fr>
parents: 10833
diff changeset
   891
    rdef_class = CubicWebRelationDefinitionSchema
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   892
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   893
    def __init__(self, schema=None, rdef=None, eid=None, **kwargs):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   894
        if rdef is not None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   895
            # if this relation is inlined
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   896
            self.inlined = rdef.inlined
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   897
        super(CubicWebRelationSchema, self).__init__(schema, rdef, **kwargs)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   898
        if eid is None and rdef is not None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   899
            eid = getattr(rdef, 'eid', None)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   900
        self.eid = eid
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   901
10553
1d824df4f2bd Fix (de)serialization of ComputedRelation read permissions
Julien Cristau <julien.cristau@logilab.fr>
parents: 10552
diff changeset
   902
    def init_computed_relation(self, rdef):
1d824df4f2bd Fix (de)serialization of ComputedRelation read permissions
Julien Cristau <julien.cristau@logilab.fr>
parents: 10552
diff changeset
   903
        self.ACTIONS = ('read',)
1d824df4f2bd Fix (de)serialization of ComputedRelation read permissions
Julien Cristau <julien.cristau@logilab.fr>
parents: 10552
diff changeset
   904
        super(CubicWebRelationSchema, self).init_computed_relation(rdef)
1d824df4f2bd Fix (de)serialization of ComputedRelation read permissions
Julien Cristau <julien.cristau@logilab.fr>
parents: 10552
diff changeset
   905
1d824df4f2bd Fix (de)serialization of ComputedRelation read permissions
Julien Cristau <julien.cristau@logilab.fr>
parents: 10552
diff changeset
   906
    def advertise_new_add_permission(self):
1d824df4f2bd Fix (de)serialization of ComputedRelation read permissions
Julien Cristau <julien.cristau@logilab.fr>
parents: 10552
diff changeset
   907
        pass
1d824df4f2bd Fix (de)serialization of ComputedRelation read permissions
Julien Cristau <julien.cristau@logilab.fr>
parents: 10552
diff changeset
   908
1d824df4f2bd Fix (de)serialization of ComputedRelation read permissions
Julien Cristau <julien.cristau@logilab.fr>
parents: 10552
diff changeset
   909
    def check_permission_definitions(self):
1d824df4f2bd Fix (de)serialization of ComputedRelation read permissions
Julien Cristau <julien.cristau@logilab.fr>
parents: 10552
diff changeset
   910
        RelationSchema.check_permission_definitions(self)
1d824df4f2bd Fix (de)serialization of ComputedRelation read permissions
Julien Cristau <julien.cristau@logilab.fr>
parents: 10552
diff changeset
   911
        PermissionMixIn.check_permission_definitions(self)
1d824df4f2bd Fix (de)serialization of ComputedRelation read permissions
Julien Cristau <julien.cristau@logilab.fr>
parents: 10552
diff changeset
   912
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
   913
    @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
   914
    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
   915
        return self.type in META_RTYPES
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   916
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   917
    def schema_relation(self):  # XXX @property for consistency with meta
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
   918
        """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
   919
        return self.type in SCHEMA_TYPES
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   920
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   921
    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
   922
        if eschema is not None:
4019
7f68077d2c3b api update
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4005
diff changeset
   923
            for tschema in self.targets(eschema, role):
7f68077d2c3b api update
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4005
diff changeset
   924
                rdef = self.role_rdef(eschema, tschema, role)
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   925
                if rdef.may_have_permission(action, req):
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   926
                    return True
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   927
        else:
10663
54b8a1f249fb [py3k] dict.itervalues → dict.values
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10662
diff changeset
   928
            for rdef in self.rdefs.values():
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   929
                if rdef.may_have_permission(action, req):
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   930
                    return True
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   931
        return False
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   932
8540
fee98af8bb33 [schema] rename schema permissions function: session may also be a request, use _cw
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8258
diff changeset
   933
    def has_perm(self, _cw, action, **kwargs):
10283
8e6aa8ed6ee1 [schema] typo
Julien Cristau <julien.cristau@logilab.fr>
parents: 10193
diff changeset
   934
        """return true if the action is granted globally or locally"""
4575
4a7fe84f7803 [schema] fix RelationSchema.has_perm to properly works with attribute relations
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4574
diff changeset
   935
        if self.final:
4a7fe84f7803 [schema] fix RelationSchema.has_perm to properly works with attribute relations
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4574
diff changeset
   936
            assert not ('fromeid' in kwargs or 'toeid' in kwargs), kwargs
4a7fe84f7803 [schema] fix RelationSchema.has_perm to properly works with attribute relations
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4574
diff changeset
   937
            assert action in ('read', 'update')
4a7fe84f7803 [schema] fix RelationSchema.has_perm to properly works with attribute relations
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4574
diff changeset
   938
            if 'eid' in kwargs:
11765
9cb215e833b0 [cnx] Use entity_type instead of entity_metas()['type']
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11681
diff changeset
   939
                subjtype = _cw.entity_type(kwargs['eid'])
4575
4a7fe84f7803 [schema] fix RelationSchema.has_perm to properly works with attribute relations
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4574
diff changeset
   940
            else:
4a7fe84f7803 [schema] fix RelationSchema.has_perm to properly works with attribute relations
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4574
diff changeset
   941
                subjtype = objtype = None
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   942
        else:
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
   943
            assert 'eid' not in kwargs, kwargs
4575
4a7fe84f7803 [schema] fix RelationSchema.has_perm to properly works with attribute relations
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4574
diff changeset
   944
            assert action in ('read', 'add', 'delete')
4a7fe84f7803 [schema] fix RelationSchema.has_perm to properly works with attribute relations
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4574
diff changeset
   945
            if 'fromeid' in kwargs:
11765
9cb215e833b0 [cnx] Use entity_type instead of entity_metas()['type']
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11681
diff changeset
   946
                subjtype = _cw.entity_type(kwargs['fromeid'])
5746
f4fc424747db [security] SchemaRelation.has_perm grows to new arguments allowing to specify subject/object entity type when actual eid are not known, but their types are
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5703
diff changeset
   947
            elif 'frometype' in kwargs:
f4fc424747db [security] SchemaRelation.has_perm grows to new arguments allowing to specify subject/object entity type when actual eid are not known, but their types are
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5703
diff changeset
   948
                subjtype = kwargs.pop('frometype')
4575
4a7fe84f7803 [schema] fix RelationSchema.has_perm to properly works with attribute relations
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4574
diff changeset
   949
            else:
4a7fe84f7803 [schema] fix RelationSchema.has_perm to properly works with attribute relations
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4574
diff changeset
   950
                subjtype = None
4a7fe84f7803 [schema] fix RelationSchema.has_perm to properly works with attribute relations
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4574
diff changeset
   951
            if 'toeid' in kwargs:
11765
9cb215e833b0 [cnx] Use entity_type instead of entity_metas()['type']
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11681
diff changeset
   952
                objtype = _cw.entity_type(kwargs['toeid'])
5746
f4fc424747db [security] SchemaRelation.has_perm grows to new arguments allowing to specify subject/object entity type when actual eid are not known, but their types are
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5703
diff changeset
   953
            elif 'toetype' in kwargs:
f4fc424747db [security] SchemaRelation.has_perm grows to new arguments allowing to specify subject/object entity type when actual eid are not known, but their types are
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5703
diff changeset
   954
                objtype = kwargs.pop('toetype')
4575
4a7fe84f7803 [schema] fix RelationSchema.has_perm to properly works with attribute relations
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4574
diff changeset
   955
            else:
4a7fe84f7803 [schema] fix RelationSchema.has_perm to properly works with attribute relations
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4574
diff changeset
   956
                objtype = None
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   957
        if objtype and subjtype:
8540
fee98af8bb33 [schema] rename schema permissions function: session may also be a request, use _cw
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8258
diff changeset
   958
            return self.rdef(subjtype, objtype).has_perm(_cw, action, **kwargs)
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   959
        elif subjtype:
4004
c52619c738a5 api renaming update
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4003
diff changeset
   960
            for tschema in self.targets(subjtype, 'subject'):
c52619c738a5 api renaming update
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4003
diff changeset
   961
                rdef = self.rdef(subjtype, tschema)
8540
fee98af8bb33 [schema] rename schema permissions function: session may also be a request, use _cw
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8258
diff changeset
   962
                if not rdef.has_perm(_cw, action, **kwargs):
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   963
                    return False
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   964
        elif objtype:
4004
c52619c738a5 api renaming update
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4003
diff changeset
   965
            for tschema in self.targets(objtype, 'object'):
c52619c738a5 api renaming update
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 4003
diff changeset
   966
                rdef = self.rdef(tschema, objtype)
8540
fee98af8bb33 [schema] rename schema permissions function: session may also be a request, use _cw
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8258
diff changeset
   967
                if not rdef.has_perm(_cw, action, **kwargs):
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   968
                    return False
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   969
        else:
10663
54b8a1f249fb [py3k] dict.itervalues → dict.values
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10662
diff changeset
   970
            for rdef in self.rdefs.values():
8540
fee98af8bb33 [schema] rename schema permissions function: session may also be a request, use _cw
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8258
diff changeset
   971
                if not rdef.has_perm(_cw, action, **kwargs):
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   972
                    return False
4233
94ffaecd8e8c ouch, has_perm was always returning False...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4181
diff changeset
   973
        return True
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   974
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   975
    @deprecated('use .rdef(subjtype, objtype).role_cardinality(role)')
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   976
    def cardinality(self, subjtype, objtype, target):
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
   977
        return self.rdef(subjtype, objtype).role_cardinality(target)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   978
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
class CubicWebSchema(Schema):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   981
    """set of entities and relations schema defining the possible data sets
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   982
    used in an application
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   983
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   984
    :type name: str
2476
1294a6bdf3bf application -> instance where it makes sense
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2460
diff changeset
   985
    :ivar name: name of the schema, usually the instance identifier
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   986
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   987
    :type base: str
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   988
    :ivar base: path of the directory where the schema is defined
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   989
    """
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   990
    reading_from_database = False
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   991
    entity_class = CubicWebEntitySchema
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   992
    relation_class = CubicWebRelationSchema
2958
44e5446b649b no inference for the identity relation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2926
diff changeset
   993
    no_specialization_inference = ('identity',)
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
    def __init__(self, *args, **kwargs):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   996
        self._eid_index = {}
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   997
        super(CubicWebSchema, self).__init__(*args, **kwargs)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   998
        ybo.register_base_types(self)
2300
c8151d004e06 meta has been drop
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2293
diff changeset
   999
        rschema = self.add_relation_type(ybo.RelationType('eid'))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1000
        rschema.final = True
2300
c8151d004e06 meta has been drop
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2293
diff changeset
  1001
        rschema = self.add_relation_type(ybo.RelationType('has_text'))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1002
        rschema.final = True
2300
c8151d004e06 meta has been drop
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2293
diff changeset
  1003
        rschema = self.add_relation_type(ybo.RelationType('identity'))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1004
        rschema.final = False
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
  1005
7440
539de926ec9d [test] fix failure introduced by 1719eab69551: the regexp should be fixed, not the error message
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7383
diff changeset
  1006
    etype_name_re = r'[A-Z][A-Za-z0-9]*[a-z]+[A-Za-z0-9]*$'
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
  1007
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1008
    def add_entity_type(self, edef):
10674
f0006bdd36e9 [py3k] bytes vs str
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10667
diff changeset
  1009
        edef.name = str(edef.name)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1010
        edef.name = bw_normalize_etype(edef.name)
7383
1719eab69551 [schema] fix imprecise error message
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7152
diff changeset
  1011
        if not re.match(self.etype_name_re, edef.name):
6861
9d4e11d6e783 [schema] ease understanding of schema naming error
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6827
diff changeset
  1012
            raise BadSchemaDefinition(
9d4e11d6e783 [schema] ease understanding of schema naming error
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6827
diff changeset
  1013
                '%r is not a valid name for an entity type. It should start '
9d4e11d6e783 [schema] ease understanding of schema naming error
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6827
diff changeset
  1014
                'with an upper cased letter and be followed by at least a '
9d4e11d6e783 [schema] ease understanding of schema naming error
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6827
diff changeset
  1015
                'lower cased letter' % edef.name)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1016
        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
  1017
        if not eschema.final:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1018
            # automatically add the eid relation to non final entity types
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1019
            rdef = ybo.RelationDefinition(eschema.type, 'eid', 'Int',
4755
13a5d3a7410e [schema] tweaks meta-relations and schema/workflow entities attributes permissions
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4754
diff changeset
  1020
                                          cardinality='11', uid=True,
13a5d3a7410e [schema] tweaks meta-relations and schema/workflow entities attributes permissions
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4754
diff changeset
  1021
                                          __permissions__=RO_ATTR_PERMS)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1022
            self.add_relation_def(rdef)
4755
13a5d3a7410e [schema] tweaks meta-relations and schema/workflow entities attributes permissions
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4754
diff changeset
  1023
            rdef = ybo.RelationDefinition(eschema.type, 'identity', eschema.type,
13a5d3a7410e [schema] tweaks meta-relations and schema/workflow entities attributes permissions
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4754
diff changeset
  1024
                                          __permissions__=RO_REL_PERMS)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1025
            self.add_relation_def(rdef)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1026
        self._eid_index[eschema.eid] = eschema
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1027
        return eschema
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
  1028
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1029
    def add_relation_type(self, rdef):
6861
9d4e11d6e783 [schema] ease understanding of schema naming error
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6827
diff changeset
  1030
        if not rdef.name.islower():
9d4e11d6e783 [schema] ease understanding of schema naming error
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6827
diff changeset
  1031
            raise BadSchemaDefinition(
9d4e11d6e783 [schema] ease understanding of schema naming error
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6827
diff changeset
  1032
                '%r is not a valid name for a relation type. It should be '
9d4e11d6e783 [schema] ease understanding of schema naming error
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6827
diff changeset
  1033
                'lower cased' % rdef.name)
10674
f0006bdd36e9 [py3k] bytes vs str
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10667
diff changeset
  1034
        rdef.name = str(rdef.name)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1035
        rschema = super(CubicWebSchema, self).add_relation_type(rdef)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1036
        self._eid_index[rschema.eid] = rschema
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1037
        return rschema
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
  1038
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1039
    def add_relation_def(self, rdef):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1040
        """build a part of a relation schema
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1041
        (i.e. add a relation between two specific entity's types)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1042
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1043
        :type subject: str
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1044
        :param subject: entity's type that is subject of the relation
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1045
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1046
        :type rtype: str
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1047
        :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
  1048
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1049
        :type obj: str
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1050
        :param obj: entity's type that is object of the relation
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1051
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1052
        :rtype: RelationSchema
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1053
        :param: the newly created or just completed relation schema
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1054
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1055
        rdef.name = rdef.name.lower()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1056
        rdef.subject = bw_normalize_etype(rdef.subject)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1057
        rdef.object = bw_normalize_etype(rdef.object)
6191
ece6996e6ac8 [schema deserial] fix loading of schema when mapping an entity type to an existing one
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6109
diff changeset
  1058
        rdefs = super(CubicWebSchema, self).add_relation_def(rdef)
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
  1059
        if rdefs:
1034
0356bbfb2f26 fix to pass arguments to base class
sylvain.thenault@logilab.fr
parents: 1016
diff changeset
  1060
            try:
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
  1061
                self._eid_index[rdef.eid] = rdefs
1034
0356bbfb2f26 fix to pass arguments to base class
sylvain.thenault@logilab.fr
parents: 1016
diff changeset
  1062
            except AttributeError:
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
  1063
                pass  # not a serialized schema
4003
b9436fe77c9e fix bad merge
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 3998
diff changeset
  1064
        return rdefs
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
  1065
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1066
    def del_relation_type(self, rtype):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1067
        rschema = self.rschema(rtype)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1068
        self._eid_index.pop(rschema.eid, None)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1069
        super(CubicWebSchema, self).del_relation_type(rtype)
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
  1070
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1071
    def del_relation_def(self, subjtype, rtype, objtype):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1072
        for k, v in self._eid_index.items():
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
  1073
            if not isinstance(v, RelationDefinitionSchema):
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
  1074
                continue
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3827
diff changeset
  1075
            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
  1076
                del self._eid_index[k]
2718
3a56b87bb5d6 [schema] break when found
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2716
diff changeset
  1077
                break
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1078
        super(CubicWebSchema, self).del_relation_def(subjtype, rtype, objtype)
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
  1079
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1080
    def del_entity_type(self, etype):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1081
        eschema = self.eschema(etype)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1082
        self._eid_index.pop(eschema.eid, None)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1083
        # deal with has_text first, else its automatic deletion (see above)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1084
        # may trigger an error in ancestor's del_entity_type method
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1085
        if 'has_text' in eschema.subject_relations():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1086
            self.del_relation_def(etype, 'has_text', 'String')
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1087
        super(CubicWebSchema, self).del_entity_type(etype)
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
  1088
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1089
    def schema_by_eid(self, eid):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1090
        return self._eid_index[eid]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1091
9967
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents: 9966
diff changeset
  1092
    def iter_computed_attributes(self):
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents: 9966
diff changeset
  1093
        for relation in self.relations():
10663
54b8a1f249fb [py3k] dict.itervalues → dict.values
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10662
diff changeset
  1094
            for rdef in relation.rdefs.values():
9967
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents: 9966
diff changeset
  1095
                if rdef.final and rdef.formula is not None:
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents: 9966
diff changeset
  1096
                    yield rdef
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents: 9966
diff changeset
  1097
9952
0f3f965b6365 [CWEP002] Add schema finalization checks for computed relations (rules)
Lea Capgen <lea.capgen@logilab.fr>, Sylvain Thénault <sylvain.thenault@logilab.fr>, Denis Laxalde <denis.laxalde@logilab.fr>
parents: 9951
diff changeset
  1098
    def iter_computed_relations(self):
0f3f965b6365 [CWEP002] Add schema finalization checks for computed relations (rules)
Lea Capgen <lea.capgen@logilab.fr>, Sylvain Thénault <sylvain.thenault@logilab.fr>, Denis Laxalde <denis.laxalde@logilab.fr>
parents: 9951
diff changeset
  1099
        for relation in self.relations():
0f3f965b6365 [CWEP002] Add schema finalization checks for computed relations (rules)
Lea Capgen <lea.capgen@logilab.fr>, Sylvain Thénault <sylvain.thenault@logilab.fr>, Denis Laxalde <denis.laxalde@logilab.fr>
parents: 9951
diff changeset
  1100
            if relation.rule:
0f3f965b6365 [CWEP002] Add schema finalization checks for computed relations (rules)
Lea Capgen <lea.capgen@logilab.fr>, Sylvain Thénault <sylvain.thenault@logilab.fr>, Denis Laxalde <denis.laxalde@logilab.fr>
parents: 9951
diff changeset
  1101
                yield relation
0f3f965b6365 [CWEP002] Add schema finalization checks for computed relations (rules)
Lea Capgen <lea.capgen@logilab.fr>, Sylvain Thénault <sylvain.thenault@logilab.fr>, Denis Laxalde <denis.laxalde@logilab.fr>
parents: 9951
diff changeset
  1102
0f3f965b6365 [CWEP002] Add schema finalization checks for computed relations (rules)
Lea Capgen <lea.capgen@logilab.fr>, Sylvain Thénault <sylvain.thenault@logilab.fr>, Denis Laxalde <denis.laxalde@logilab.fr>
parents: 9951
diff changeset
  1103
    def finalize(self):
0f3f965b6365 [CWEP002] Add schema finalization checks for computed relations (rules)
Lea Capgen <lea.capgen@logilab.fr>, Sylvain Thénault <sylvain.thenault@logilab.fr>, Denis Laxalde <denis.laxalde@logilab.fr>
parents: 9951
diff changeset
  1104
        super(CubicWebSchema, self).finalize()
9966
6c2d57d1b6de [CWEP002] Add schema finalization checks for computed attributes
Laura Médioni <laura.medioni@logilab.fr>
parents: 9963
diff changeset
  1105
        self.finalize_computed_attributes()
9952
0f3f965b6365 [CWEP002] Add schema finalization checks for computed relations (rules)
Lea Capgen <lea.capgen@logilab.fr>, Sylvain Thénault <sylvain.thenault@logilab.fr>, Denis Laxalde <denis.laxalde@logilab.fr>
parents: 9951
diff changeset
  1106
        self.finalize_computed_relations()
0f3f965b6365 [CWEP002] Add schema finalization checks for computed relations (rules)
Lea Capgen <lea.capgen@logilab.fr>, Sylvain Thénault <sylvain.thenault@logilab.fr>, Denis Laxalde <denis.laxalde@logilab.fr>
parents: 9951
diff changeset
  1107
9966
6c2d57d1b6de [CWEP002] Add schema finalization checks for computed attributes
Laura Médioni <laura.medioni@logilab.fr>
parents: 9963
diff changeset
  1108
    def finalize_computed_attributes(self):
9967
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents: 9966
diff changeset
  1109
        """Check computed attributes validity (if any), else raise
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents: 9966
diff changeset
  1110
        `BadSchemaDefinition`
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents: 9966
diff changeset
  1111
        """
9966
6c2d57d1b6de [CWEP002] Add schema finalization checks for computed attributes
Laura Médioni <laura.medioni@logilab.fr>
parents: 9963
diff changeset
  1112
        analyzer = ETypeResolver(self)
9967
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents: 9966
diff changeset
  1113
        for rdef in self.iter_computed_attributes():
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents: 9966
diff changeset
  1114
            rqlst = parse(rdef.formula)
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents: 9966
diff changeset
  1115
            select = rqlst.children[0]
10192
365e5a0287d6 [computed attribute] ensure attribute's formula apply only to the correct type. Closes #4901163
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 10140
diff changeset
  1116
            select.add_type_restriction(select.defined_vars['X'], str(rdef.subject))
9967
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents: 9966
diff changeset
  1117
            analyzer.visit(select)
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents: 9966
diff changeset
  1118
            _check_valid_formula(rdef, rqlst)
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
  1119
            rdef.formula_select = select  # avoid later recomputation
9966
6c2d57d1b6de [CWEP002] Add schema finalization checks for computed attributes
Laura Médioni <laura.medioni@logilab.fr>
parents: 9963
diff changeset
  1120
9952
0f3f965b6365 [CWEP002] Add schema finalization checks for computed relations (rules)
Lea Capgen <lea.capgen@logilab.fr>, Sylvain Thénault <sylvain.thenault@logilab.fr>, Denis Laxalde <denis.laxalde@logilab.fr>
parents: 9951
diff changeset
  1121
    def finalize_computed_relations(self):
0f3f965b6365 [CWEP002] Add schema finalization checks for computed relations (rules)
Lea Capgen <lea.capgen@logilab.fr>, Sylvain Thénault <sylvain.thenault@logilab.fr>, Denis Laxalde <denis.laxalde@logilab.fr>
parents: 9951
diff changeset
  1122
        """Build relation definitions for computed relations
0f3f965b6365 [CWEP002] Add schema finalization checks for computed relations (rules)
Lea Capgen <lea.capgen@logilab.fr>, Sylvain Thénault <sylvain.thenault@logilab.fr>, Denis Laxalde <denis.laxalde@logilab.fr>
parents: 9951
diff changeset
  1123
0f3f965b6365 [CWEP002] Add schema finalization checks for computed relations (rules)
Lea Capgen <lea.capgen@logilab.fr>, Sylvain Thénault <sylvain.thenault@logilab.fr>, Denis Laxalde <denis.laxalde@logilab.fr>
parents: 9951
diff changeset
  1124
        The subject and object types are infered using rql analyzer.
0f3f965b6365 [CWEP002] Add schema finalization checks for computed relations (rules)
Lea Capgen <lea.capgen@logilab.fr>, Sylvain Thénault <sylvain.thenault@logilab.fr>, Denis Laxalde <denis.laxalde@logilab.fr>
parents: 9951
diff changeset
  1125
        """
0f3f965b6365 [CWEP002] Add schema finalization checks for computed relations (rules)
Lea Capgen <lea.capgen@logilab.fr>, Sylvain Thénault <sylvain.thenault@logilab.fr>, Denis Laxalde <denis.laxalde@logilab.fr>
parents: 9951
diff changeset
  1126
        analyzer = ETypeResolver(self)
0f3f965b6365 [CWEP002] Add schema finalization checks for computed relations (rules)
Lea Capgen <lea.capgen@logilab.fr>, Sylvain Thénault <sylvain.thenault@logilab.fr>, Denis Laxalde <denis.laxalde@logilab.fr>
parents: 9951
diff changeset
  1127
        for rschema in self.iter_computed_relations():
0f3f965b6365 [CWEP002] Add schema finalization checks for computed relations (rules)
Lea Capgen <lea.capgen@logilab.fr>, Sylvain Thénault <sylvain.thenault@logilab.fr>, Denis Laxalde <denis.laxalde@logilab.fr>
parents: 9951
diff changeset
  1128
            # XXX rule is valid if both S and O are defined and not in an exists
0f3f965b6365 [CWEP002] Add schema finalization checks for computed relations (rules)
Lea Capgen <lea.capgen@logilab.fr>, Sylvain Thénault <sylvain.thenault@logilab.fr>, Denis Laxalde <denis.laxalde@logilab.fr>
parents: 9951
diff changeset
  1129
            rqlexpr = RRQLExpression(rschema.rule)
0f3f965b6365 [CWEP002] Add schema finalization checks for computed relations (rules)
Lea Capgen <lea.capgen@logilab.fr>, Sylvain Thénault <sylvain.thenault@logilab.fr>, Denis Laxalde <denis.laxalde@logilab.fr>
parents: 9951
diff changeset
  1130
            rqlst = rqlexpr.snippet_rqlst
0f3f965b6365 [CWEP002] Add schema finalization checks for computed relations (rules)
Lea Capgen <lea.capgen@logilab.fr>, Sylvain Thénault <sylvain.thenault@logilab.fr>, Denis Laxalde <denis.laxalde@logilab.fr>
parents: 9951
diff changeset
  1131
            analyzer.visit(rqlst)
0f3f965b6365 [CWEP002] Add schema finalization checks for computed relations (rules)
Lea Capgen <lea.capgen@logilab.fr>, Sylvain Thénault <sylvain.thenault@logilab.fr>, Denis Laxalde <denis.laxalde@logilab.fr>
parents: 9951
diff changeset
  1132
            couples = set((sol['S'], sol['O']) for sol in rqlst.solutions)
0f3f965b6365 [CWEP002] Add schema finalization checks for computed relations (rules)
Lea Capgen <lea.capgen@logilab.fr>, Sylvain Thénault <sylvain.thenault@logilab.fr>, Denis Laxalde <denis.laxalde@logilab.fr>
parents: 9951
diff changeset
  1133
            for subjtype, objtype in couples:
0f3f965b6365 [CWEP002] Add schema finalization checks for computed relations (rules)
Lea Capgen <lea.capgen@logilab.fr>, Sylvain Thénault <sylvain.thenault@logilab.fr>, Denis Laxalde <denis.laxalde@logilab.fr>
parents: 9951
diff changeset
  1134
                if self[objtype].final:
0f3f965b6365 [CWEP002] Add schema finalization checks for computed relations (rules)
Lea Capgen <lea.capgen@logilab.fr>, Sylvain Thénault <sylvain.thenault@logilab.fr>, Denis Laxalde <denis.laxalde@logilab.fr>
parents: 9951
diff changeset
  1135
                    raise BadSchemaDefinition('computed relations cannot be final')
0f3f965b6365 [CWEP002] Add schema finalization checks for computed relations (rules)
Lea Capgen <lea.capgen@logilab.fr>, Sylvain Thénault <sylvain.thenault@logilab.fr>, Denis Laxalde <denis.laxalde@logilab.fr>
parents: 9951
diff changeset
  1136
                rdef = ybo.RelationDefinition(
10193
a0a11be5a9cb [schema] set permissions that do not allow edition on computed relation. Closes #4903918
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 10192
diff changeset
  1137
                    subjtype, rschema.type, objtype,
a0a11be5a9cb [schema] set permissions that do not allow edition on computed relation. Closes #4903918
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 10192
diff changeset
  1138
                    __permissions__={'add': (),
a0a11be5a9cb [schema] set permissions that do not allow edition on computed relation. Closes #4903918
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 10192
diff changeset
  1139
                                     'delete': (),
10552
0e7fab504305 Copy read permissions on ComputedRelation rdefs
Christophe de Vienne <christophe@unlish.com>
parents: 10531
diff changeset
  1140
                                     'read': rschema.permissions['read']})
9952
0f3f965b6365 [CWEP002] Add schema finalization checks for computed relations (rules)
Lea Capgen <lea.capgen@logilab.fr>, Sylvain Thénault <sylvain.thenault@logilab.fr>, Denis Laxalde <denis.laxalde@logilab.fr>
parents: 9951
diff changeset
  1141
                rdef.infered = True
0f3f965b6365 [CWEP002] Add schema finalization checks for computed relations (rules)
Lea Capgen <lea.capgen@logilab.fr>, Sylvain Thénault <sylvain.thenault@logilab.fr>, Denis Laxalde <denis.laxalde@logilab.fr>
parents: 9951
diff changeset
  1142
                self.add_relation_def(rdef)
0f3f965b6365 [CWEP002] Add schema finalization checks for computed relations (rules)
Lea Capgen <lea.capgen@logilab.fr>, Sylvain Thénault <sylvain.thenault@logilab.fr>, Denis Laxalde <denis.laxalde@logilab.fr>
parents: 9951
diff changeset
  1143
9963
5531f5577b50 [CWEP002 migration] support add_relation_type for computed relations
Laura Médioni <laura.medioni@logilab.fr>
parents: 9958
diff changeset
  1144
    def rebuild_infered_relations(self):
5531f5577b50 [CWEP002 migration] support add_relation_type for computed relations
Laura Médioni <laura.medioni@logilab.fr>
parents: 9958
diff changeset
  1145
        super(CubicWebSchema, self).rebuild_infered_relations()
11039
6424a2e112f5 [schema] rebuild computed attributes on schema reload
Julien Cristau <julien.cristau@logilab.fr>
parents: 10834
diff changeset
  1146
        self.finalize_computed_attributes()
9963
5531f5577b50 [CWEP002 migration] support add_relation_type for computed relations
Laura Médioni <laura.medioni@logilab.fr>
parents: 9958
diff changeset
  1147
        self.finalize_computed_relations()
5531f5577b50 [CWEP002 migration] support add_relation_type for computed relations
Laura Médioni <laura.medioni@logilab.fr>
parents: 9958
diff changeset
  1148
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1149
7152
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1150
# additional cw specific constraints ###########################################
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1151
11416
9c2fbb872e91 [schema] Add a method on yams constraints to compute its unique name
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11344
diff changeset
  1152
@monkeypatch(BaseConstraint)
9c2fbb872e91 [schema] Add a method on yams constraints to compute its unique name
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11344
diff changeset
  1153
def name_for(self, rdef):
9c2fbb872e91 [schema] Add a method on yams constraints to compute its unique name
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11344
diff changeset
  1154
    """Return a unique, size controlled, name for this constraint applied to given `rdef`.
9c2fbb872e91 [schema] Add a method on yams constraints to compute its unique name
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11344
diff changeset
  1155
9c2fbb872e91 [schema] Add a method on yams constraints to compute its unique name
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11344
diff changeset
  1156
    This name may be used as name for the constraint in the database.
9c2fbb872e91 [schema] Add a method on yams constraints to compute its unique name
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11344
diff changeset
  1157
    """
9c2fbb872e91 [schema] Add a method on yams constraints to compute its unique name
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11344
diff changeset
  1158
    return 'cstr' + md5((rdef.subject.type + rdef.rtype.type + self.type() +
9c2fbb872e91 [schema] Add a method on yams constraints to compute its unique name
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11344
diff changeset
  1159
                         (self.serialize() or '')).encode('ascii')).hexdigest()
9c2fbb872e91 [schema] Add a method on yams constraints to compute its unique name
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11344
diff changeset
  1160
9c2fbb872e91 [schema] Add a method on yams constraints to compute its unique name
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11344
diff changeset
  1161
7152
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1162
class BaseRQLConstraint(RRQLExpression, BaseConstraint):
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1163
    """base class for rql constraints"""
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1164
    distinct_query = None
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1165
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1166
    def serialize(self):
11215
4e79acdc36a6 [schema] use json to serialize constraints
Julien Cristau <julien.cristau@logilab.fr>
parents: 11151
diff changeset
  1167
        return cstr_json_dumps({u'mainvars': sorted(self.mainvars),
4e79acdc36a6 [schema] use json to serialize constraints
Julien Cristau <julien.cristau@logilab.fr>
parents: 11151
diff changeset
  1168
                                u'expression': self.expression})
7152
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1169
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1170
    @classmethod
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1171
    def deserialize(cls, value):
11215
4e79acdc36a6 [schema] use json to serialize constraints
Julien Cristau <julien.cristau@logilab.fr>
parents: 11151
diff changeset
  1172
        try:
4e79acdc36a6 [schema] use json to serialize constraints
Julien Cristau <julien.cristau@logilab.fr>
parents: 11151
diff changeset
  1173
            d = cstr_json_loads(value)
4e79acdc36a6 [schema] use json to serialize constraints
Julien Cristau <julien.cristau@logilab.fr>
parents: 11151
diff changeset
  1174
            return cls(d['expression'], d['mainvars'])
4e79acdc36a6 [schema] use json to serialize constraints
Julien Cristau <julien.cristau@logilab.fr>
parents: 11151
diff changeset
  1175
        except ValueError:
4e79acdc36a6 [schema] use json to serialize constraints
Julien Cristau <julien.cristau@logilab.fr>
parents: 11151
diff changeset
  1176
            _, mainvars, expression = value.split(';', 2)
4e79acdc36a6 [schema] use json to serialize constraints
Julien Cristau <julien.cristau@logilab.fr>
parents: 11151
diff changeset
  1177
            return cls(expression, mainvars)
7152
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1178
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1179
    def check(self, entity, rtype, value):
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1180
        """return true if the value satisfy the constraint, else false"""
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1181
        # implemented as a hook in the repository
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1182
        return 1
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1183
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1184
    def __str__(self):
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1185
        if self.distinct_query:
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1186
            selop = 'Any'
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1187
        else:
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1188
            selop = 'DISTINCT Any'
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1189
        return '%s(%s %s WHERE %s)' % (self.__class__.__name__, selop,
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1190
                                       ','.join(sorted(self.mainvars)),
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1191
                                       self.expression)
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1192
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1193
    def __repr__(self):
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1194
        return '<%s @%#x>' % (self.__str__(), id(self))
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1195
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1196
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1197
class RQLVocabularyConstraint(BaseRQLConstraint):
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1198
    """the rql vocabulary constraint:
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1199
10140
e14ec2aac099 [schema] Typo and indentation fix in RQLVocabularyConstraint doc string
Julien Cristau <julien.cristau@logilab.fr>
parents: 9990
diff changeset
  1200
    limits the proposed values to a set of entities returned by an rql query,
7152
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1201
    but this is not enforced at the repository level
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1202
10140
e14ec2aac099 [schema] Typo and indentation fix in RQLVocabularyConstraint doc string
Julien Cristau <julien.cristau@logilab.fr>
parents: 9990
diff changeset
  1203
    `expression` is an additional rql restriction that will be added to
e14ec2aac099 [schema] Typo and indentation fix in RQLVocabularyConstraint doc string
Julien Cristau <julien.cristau@logilab.fr>
parents: 9990
diff changeset
  1204
    a predefined query, where the S and O variables respectively represent
e14ec2aac099 [schema] Typo and indentation fix in RQLVocabularyConstraint doc string
Julien Cristau <julien.cristau@logilab.fr>
parents: 9990
diff changeset
  1205
    the subject and the object of the relation
7152
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1206
10140
e14ec2aac099 [schema] Typo and indentation fix in RQLVocabularyConstraint doc string
Julien Cristau <julien.cristau@logilab.fr>
parents: 9990
diff changeset
  1207
    `mainvars` is a set of variables that should be used as selection variables
e14ec2aac099 [schema] Typo and indentation fix in RQLVocabularyConstraint doc string
Julien Cristau <julien.cristau@logilab.fr>
parents: 9990
diff changeset
  1208
    (i.e. `'Any %s WHERE ...' % mainvars`). If not specified, an attempt will be
e14ec2aac099 [schema] Typo and indentation fix in RQLVocabularyConstraint doc string
Julien Cristau <julien.cristau@logilab.fr>
parents: 9990
diff changeset
  1209
    made to guess it based on the variables used in the expression.
7152
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1210
    """
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1211
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1212
    def repo_check(self, session, eidfrom, rtype, eidto):
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1213
        """raise ValidationError if the relation doesn't satisfy the constraint
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1214
        """
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
  1215
        pass  # this is a vocabulary constraint, not enforced
7152
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1216
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1217
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1218
class RepoEnforcedRQLConstraintMixIn(object):
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1219
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1220
    def __init__(self, expression, mainvars=None, msg=None):
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1221
        super(RepoEnforcedRQLConstraintMixIn, self).__init__(expression, mainvars)
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1222
        self.msg = msg
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1223
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1224
    def serialize(self):
11215
4e79acdc36a6 [schema] use json to serialize constraints
Julien Cristau <julien.cristau@logilab.fr>
parents: 11151
diff changeset
  1225
        return cstr_json_dumps({
4e79acdc36a6 [schema] use json to serialize constraints
Julien Cristau <julien.cristau@logilab.fr>
parents: 11151
diff changeset
  1226
            u'mainvars': sorted(self.mainvars),
4e79acdc36a6 [schema] use json to serialize constraints
Julien Cristau <julien.cristau@logilab.fr>
parents: 11151
diff changeset
  1227
            u'expression': self.expression,
4e79acdc36a6 [schema] use json to serialize constraints
Julien Cristau <julien.cristau@logilab.fr>
parents: 11151
diff changeset
  1228
            u'msg': self.msg})
7152
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1229
10797
b4f8c0b98c29 [schema] use classmethod decorator
Julien Cristau <julien.cristau@logilab.fr>
parents: 10791
diff changeset
  1230
    @classmethod
7152
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1231
    def deserialize(cls, value):
11215
4e79acdc36a6 [schema] use json to serialize constraints
Julien Cristau <julien.cristau@logilab.fr>
parents: 11151
diff changeset
  1232
        try:
4e79acdc36a6 [schema] use json to serialize constraints
Julien Cristau <julien.cristau@logilab.fr>
parents: 11151
diff changeset
  1233
            d = cstr_json_loads(value)
4e79acdc36a6 [schema] use json to serialize constraints
Julien Cristau <julien.cristau@logilab.fr>
parents: 11151
diff changeset
  1234
            return cls(d['expression'], d['mainvars'], d['msg'])
4e79acdc36a6 [schema] use json to serialize constraints
Julien Cristau <julien.cristau@logilab.fr>
parents: 11151
diff changeset
  1235
        except ValueError:
4e79acdc36a6 [schema] use json to serialize constraints
Julien Cristau <julien.cristau@logilab.fr>
parents: 11151
diff changeset
  1236
            value, msg = value.split('\n', 1)
4e79acdc36a6 [schema] use json to serialize constraints
Julien Cristau <julien.cristau@logilab.fr>
parents: 11151
diff changeset
  1237
            _, mainvars, expression = value.split(';', 2)
4e79acdc36a6 [schema] use json to serialize constraints
Julien Cristau <julien.cristau@logilab.fr>
parents: 11151
diff changeset
  1238
            return cls(expression, mainvars, msg)
7152
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1239
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1240
    def repo_check(self, session, eidfrom, rtype, eidto=None):
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1241
        """raise ValidationError if the relation doesn't satisfy the constraint
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1242
        """
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1243
        if not self.match_condition(session, eidfrom, eidto):
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1244
            # XXX at this point if both or neither of S and O are in mainvar we
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1245
            # dunno if the validation error `occurred` on eidfrom or eidto (from
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1246
            # user interface point of view)
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1247
            #
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1248
            # possible enhancement: check entity being created, it's probably
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1249
            # the main eid unless this is a composite relation
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1250
            if eidto is None or 'S' in self.mainvars or not 'O' in self.mainvars:
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1251
                maineid = eidfrom
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1252
                qname = role_name(rtype, 'subject')
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1253
            else:
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1254
                maineid = eidto
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1255
                qname = role_name(rtype, 'object')
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1256
            if self.msg:
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1257
                msg = session._(self.msg)
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1258
            else:
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1259
                msg = '%(constraint)s %(expression)s failed' % {
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1260
                    'constraint':  session._(self.type()),
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1261
                    'expression': self.expression}
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1262
            raise ValidationError(maineid, {qname: msg})
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1263
8540
fee98af8bb33 [schema] rename schema permissions function: session may also be a request, use _cw
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8258
diff changeset
  1264
    def exec_query(self, _cw, eidfrom, eidto):
7152
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1265
        if eidto is None:
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1266
            # checking constraint for an attribute relation
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1267
            expression = 'S eid %(s)s, ' + self.expression
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1268
            args = {'s': eidfrom}
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1269
        else:
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1270
            expression = 'S eid %(s)s, O eid %(o)s, ' + self.expression
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1271
            args = {'s': eidfrom, 'o': eidto}
11343
892e4c12f03f [schema] Avoid parsing RQL expressions twice on schema loading
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 11215
diff changeset
  1272
        if 'U' in self.snippet_rqlst.defined_vars:
7640
85ebdbbcb321 [schema] closes #1816439: RQLConstraint does not take variable U into account
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7603
diff changeset
  1273
            expression = 'U eid %(u)s, ' + expression
8540
fee98af8bb33 [schema] rename schema permissions function: session may also be a request, use _cw
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8258
diff changeset
  1274
            args['u'] = _cw.user.eid
7152
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1275
        rql = 'Any %s WHERE %s' % (','.join(sorted(self.mainvars)), expression)
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1276
        if self.distinct_query:
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1277
            rql = 'DISTINCT ' + rql
8540
fee98af8bb33 [schema] rename schema permissions function: session may also be a request, use _cw
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8258
diff changeset
  1278
        return _cw.execute(rql, args, build_descr=False)
7152
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1279
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1280
10833
f585add0fed9 [schema] Let RQLConstraint inherit from BaseRQLConstraint instead of RQLVocabularyConstraint
Denis Laxalde <denis.laxalde@logilab.fr>, Rémi Cardona <remi.cardona@logilab.fr>
parents: 10813
diff changeset
  1281
class RQLConstraint(RepoEnforcedRQLConstraintMixIn, BaseRQLConstraint):
7152
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1282
    """the rql constraint is similar to the RQLVocabularyConstraint but
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1283
    are also enforced at the repository level
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1284
    """
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1285
    distinct_query = False
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1286
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1287
    def match_condition(self, session, eidfrom, eidto):
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1288
        return self.exec_query(session, eidfrom, eidto)
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1289
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1290
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1291
class RQLUniqueConstraint(RepoEnforcedRQLConstraintMixIn, BaseRQLConstraint):
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1292
    """the unique rql constraint check that the result of the query isn't
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1293
    greater than one.
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1294
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1295
    You *must* specify `mainvars` when instantiating the constraint since there
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1296
    is no way to guess it correctly (e.g. if using S,O or U the constraint will
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1297
    always be satisfied because we've to use a DISTINCT query).
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1298
    """
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1299
    # XXX turns mainvars into a required argument in __init__
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1300
    distinct_query = True
9227
762a331db741 [schema] fix spurious warning when rqlexpr/constraint mainvars specify a non predefined variable. Closes #3098165
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9173
diff changeset
  1301
7152
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1302
    def match_condition(self, session, eidfrom, eidto):
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1303
        return len(self.exec_query(session, eidfrom, eidto)) <= 1
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1304
39c1ffc7d93f [schema, refactoring] use RQLExpression as base class for RQL constraint classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7103
diff changeset
  1305
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
  1306
# 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
  1307
2460
ce1a7ffc6c90 fix a couple NameErrors
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2459
diff changeset
  1308
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
  1309
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
  1310
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
  1311
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
  1312
    """extends default EntityType's metaclass to add workflow relations
5378
0f54a0e128ac [schema] cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5372
diff changeset
  1313
    (i.e. in_state, wf_info_for and custom_workflow). This is the default
0f54a0e128ac [schema] cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5372
diff changeset
  1314
    metaclass for WorkflowableEntityType.
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
  1315
    """
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
  1316
    def __new__(mcs, name, bases, classdict):
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
  1317
        abstract = classdict.pop('__abstract__', False)
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
  1318
        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
  1319
                                                          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
  1320
        if not abstract:
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
  1321
            make_workflowable(cls)
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
  1322
        return cls
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
  1323
10667
c23dc4f7467a [py3k] declare meta classes using six.add_metaclass
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10666
diff changeset
  1324
c23dc4f7467a [py3k] declare meta classes using six.add_metaclass
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10666
diff changeset
  1325
@add_metaclass(workflowable_definition)
5379
c082dea0731b [schema] update for yams 0.29: BoundConstraint renamed to BoundaryConstraint; new constraint messages; ObjectRelation deprecated
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5378
diff changeset
  1326
class WorkflowableEntityType(ybo.EntityType):
c082dea0731b [schema] update for yams 0.29: BoundConstraint renamed to BoundaryConstraint; new constraint messages; ObjectRelation deprecated
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5378
diff changeset
  1327
    """Use this base class instead of :class:`EntityType` to have workflow
c082dea0731b [schema] update for yams 0.29: BoundConstraint renamed to BoundaryConstraint; new constraint messages; ObjectRelation deprecated
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5378
diff changeset
  1328
    relations (i.e. `in_state`, `wf_info_for` and `custom_workflow`) on your
c082dea0731b [schema] update for yams 0.29: BoundConstraint renamed to BoundaryConstraint; new constraint messages; ObjectRelation deprecated
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5378
diff changeset
  1329
    entity type.
c082dea0731b [schema] update for yams 0.29: BoundConstraint renamed to BoundaryConstraint; new constraint messages; ObjectRelation deprecated
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5378
diff changeset
  1330
    """
c082dea0731b [schema] update for yams 0.29: BoundConstraint renamed to BoundaryConstraint; new constraint messages; ObjectRelation deprecated
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5378
diff changeset
  1331
    __abstract__ = True
c082dea0731b [schema] update for yams 0.29: BoundConstraint renamed to BoundaryConstraint; new constraint messages; ObjectRelation deprecated
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5378
diff changeset
  1332
c082dea0731b [schema] update for yams 0.29: BoundConstraint renamed to BoundaryConstraint; new constraint messages; ObjectRelation deprecated
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5378
diff changeset
  1333
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
  1334
def make_workflowable(cls, in_state_descr=None):
5378
0f54a0e128ac [schema] cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5372
diff changeset
  1335
    """Adds workflow relations as :class:`WorkflowableEntityType`, but usable on
0f54a0e128ac [schema] cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5372
diff changeset
  1336
    existing classes which are not using that base class.
0f54a0e128ac [schema] cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5372
diff changeset
  1337
    """
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
  1338
    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
  1339
    # 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
  1340
    # cardinality, constraints and other relation definition properties
5379
c082dea0731b [schema] update for yams 0.29: BoundConstraint renamed to BoundaryConstraint; new constraint messages; ObjectRelation deprecated
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5378
diff changeset
  1341
    etype = getattr(cls, 'name', cls.__name__)
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
  1342
    if 'custom_workflow' not in existing_rels:
5379
c082dea0731b [schema] update for yams 0.29: BoundConstraint renamed to BoundaryConstraint; new constraint messages; ObjectRelation deprecated
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5378
diff changeset
  1343
        rdef = ybo.RelationDefinition(etype, 'custom_workflow', 'Workflow')
c082dea0731b [schema] update for yams 0.29: BoundConstraint renamed to BoundaryConstraint; new constraint messages; ObjectRelation deprecated
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5378
diff changeset
  1344
        yams_add_relation(cls.__relations__, rdef)
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
  1345
    if 'in_state' not in existing_rels:
5379
c082dea0731b [schema] update for yams 0.29: BoundConstraint renamed to BoundaryConstraint; new constraint messages; ObjectRelation deprecated
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5378
diff changeset
  1346
        rdef = ybo.RelationDefinition(etype, 'in_state', 'State',
c082dea0731b [schema] update for yams 0.29: BoundConstraint renamed to BoundaryConstraint; new constraint messages; ObjectRelation deprecated
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5378
diff changeset
  1347
                                      description=in_state_descr)
c082dea0731b [schema] update for yams 0.29: BoundConstraint renamed to BoundaryConstraint; new constraint messages; ObjectRelation deprecated
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5378
diff changeset
  1348
        yams_add_relation(cls.__relations__, rdef)
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2782
diff changeset
  1349
    if 'wf_info_for' not in existing_rels:
5379
c082dea0731b [schema] update for yams 0.29: BoundConstraint renamed to BoundaryConstraint; new constraint messages; ObjectRelation deprecated
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5378
diff changeset
  1350
        rdef = ybo.RelationDefinition('TrInfo', 'wf_info_for', etype)
c082dea0731b [schema] update for yams 0.29: BoundConstraint renamed to BoundaryConstraint; new constraint messages; ObjectRelation deprecated
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5378
diff changeset
  1351
        yams_add_relation(cls.__relations__, rdef)
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
  1352
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
  1353
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1354
# schema loading ##############################################################
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1355
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1356
CONSTRAINTS['RQLConstraint'] = RQLConstraint
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1357
CONSTRAINTS['RQLUniqueConstraint'] = RQLUniqueConstraint
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1358
CONSTRAINTS['RQLVocabularyConstraint'] = RQLVocabularyConstraint
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
  1359
# don't want MultipleStaticVocabularyConstraint in cw yams schema
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
  1360
CONSTRAINTS.pop('MultipleStaticVocabularyConstraint', None)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1361
PyFileReader.context.update(CONSTRAINTS)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1362
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1363
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1364
class BootstrapSchemaLoader(SchemaLoader):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1365
    """cubicweb specific schema loader, loading only schema necessary to read
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1366
    the persistent schema
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1367
    """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1368
    schemacls = CubicWebSchema
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1369
1034
0356bbfb2f26 fix to pass arguments to base class
sylvain.thenault@logilab.fr
parents: 1016
diff changeset
  1370
    def load(self, config, path=(), **kwargs):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1371
        """return a Schema instance from the schema definition read
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1372
        from <directory>
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1373
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1374
        return super(BootstrapSchemaLoader, self).load(
1034
0356bbfb2f26 fix to pass arguments to base class
sylvain.thenault@logilab.fr
parents: 1016
diff changeset
  1375
            path, config.appid, register_base_types=False, **kwargs)
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
  1376
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1377
    def _load_definition_files(self, cubes=None):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1378
        # bootstraping, ignore cubes
2735
39c942241b48 no need for lib_directory
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2730
diff changeset
  1379
        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
  1380
        self.info('loading %s', filepath)
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
  1381
        with tempattr(ybo, 'PACKAGE', 'cubicweb'):  # though we don't care here
9366
bcbc92223b35 set proper PACKAGE information for yams 0.39
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9283
diff changeset
  1382
            self.handle_file(filepath)
1451
982e8616d9a2 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
  1383
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1384
    def unhandled_file(self, filepath):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1385
        """called when a file without handler associated has been found"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1386
        self.warning('ignoring file %r', filepath)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1387
7083
b8e35cde46e9 help pylint by explicitely defining some attributes
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6861
diff changeset
  1388
    # these are overridden by set_log_methods below
b8e35cde46e9 help pylint by explicitely defining some attributes
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6861
diff changeset
  1389
    # only defining here to prevent pylint from complaining
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
  1390
    info = warning = error = critical = exception = debug = lambda msg, *a, **kw: None
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
  1391
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1392
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1393
class CubicWebSchemaLoader(BootstrapSchemaLoader):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1394
    """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
  1395
    instance's schema
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1396
    """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1397
1034
0356bbfb2f26 fix to pass arguments to base class
sylvain.thenault@logilab.fr
parents: 1016
diff changeset
  1398
    def load(self, config, **kwargs):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1399
        """return a Schema instance from the schema definition read
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1400
        from <directory>
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1401
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1402
        self.info('loading %s schemas', ', '.join(config.cubes()))
11446
ca90cd9b112b [schema] Set CubicWebSchemaLoader's extrapath using config eponymous property
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11417
diff changeset
  1403
        self.extrapath = config.extrapath
372
a8a975a88368 check apphome is not None
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 0
diff changeset
  1404
        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
  1405
            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
  1406
        else:
2598
a66fe74bd9fc [R schema] dont give an iterator, it's a trap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2596
diff changeset
  1407
            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
  1408
        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
  1409
            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
  1410
        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
  1411
            # 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
  1412
            cleanup_sys_modules([join(cubicweb.CW_SOFTWARE_ROOT, 'schemas')])
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1413
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1414
    def _load_definition_files(self, cubes):
2741
148d0cea1fb5 [schema] oops
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2736
diff changeset
  1415
        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
  1416
                         join(cubicweb.CW_SOFTWARE_ROOT, 'schemas', 'base.py'),
148d0cea1fb5 [schema] oops
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2736
diff changeset
  1417
                         join(cubicweb.CW_SOFTWARE_ROOT, 'schemas', 'workflow.py'),
148d0cea1fb5 [schema] oops
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2736
diff changeset
  1418
                         join(cubicweb.CW_SOFTWARE_ROOT, 'schemas', 'Bookmark.py')):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1419
            self.info('loading %s', filepath)
9366
bcbc92223b35 set proper PACKAGE information for yams 0.39
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9283
diff changeset
  1420
            with tempattr(ybo, 'PACKAGE', 'cubicweb'):
bcbc92223b35 set proper PACKAGE information for yams 0.39
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9283
diff changeset
  1421
                self.handle_file(filepath)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1422
        for cube in cubes:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1423
            for filepath in self.get_schema_files(cube):
9366
bcbc92223b35 set proper PACKAGE information for yams 0.39
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9283
diff changeset
  1424
                with tempattr(ybo, 'PACKAGE', basename(cube)):
bcbc92223b35 set proper PACKAGE information for yams 0.39
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9283
diff changeset
  1425
                    self.handle_file(filepath)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1426
7083
b8e35cde46e9 help pylint by explicitely defining some attributes
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6861
diff changeset
  1427
    # these are overridden by set_log_methods below
b8e35cde46e9 help pylint by explicitely defining some attributes
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6861
diff changeset
  1428
    # only defining here to prevent pylint from complaining
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
  1429
    info = warning = error = critical = exception = debug = lambda msg, *a, **kw: None
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1430
9967
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents: 9966
diff changeset
  1431
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
  1432
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
  1433
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
  1434
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
  1435
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1436
# _() 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
  1437
# translation
7797
a71618a75b53 backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7782
diff changeset
  1438
MAY_USE_TEMPLATE_FORMAT = set(('managers',))
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
  1439
NEED_PERM_FORMATS = [_('text/cubicweb-page-template')]
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1440
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
  1441
2531
531ea4e7013e [cleanup] nicer imports
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2526
diff changeset
  1442
@monkeypatch(FormatConstraint)
3347
428f95118556 fix vocab param to avoid deprecation warning
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3287
diff changeset
  1443
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
  1444
    cw = None
3347
428f95118556 fix vocab param to avoid deprecation warning
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3287
diff changeset
  1445
    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
  1446
        cw = entity._cw
3347
428f95118556 fix vocab param to avoid deprecation warning
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3287
diff changeset
  1447
    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
  1448
        cw = form._cw
4757
5d937aeaa6fb do not check for use template permission when session is super session or integrity hooks are deactivated
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4755
diff changeset
  1449
    if cw is not None:
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
  1450
        if hasattr(cw, 'write_security'):  # test it's a session and not a request
4757
5d937aeaa6fb do not check for use template permission when session is super session or integrity hooks are deactivated
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4755
diff changeset
  1451
            # cw is a server session
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
  1452
            hasperm = (not cw.write_security or
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
  1453
                       not cw.is_hook_category_activated('integrity') or
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
  1454
                       cw.user.matching_groups(MAY_USE_TEMPLATE_FORMAT))
4757
5d937aeaa6fb do not check for use template permission when session is super session or integrity hooks are deactivated
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4755
diff changeset
  1455
        else:
7797
a71618a75b53 backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7782
diff changeset
  1456
            hasperm = cw.user.matching_groups(MAY_USE_TEMPLATE_FORMAT)
4757
5d937aeaa6fb do not check for use template permission when session is super session or integrity hooks are deactivated
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4755
diff changeset
  1457
        if hasperm:
5d937aeaa6fb do not check for use template permission when session is super session or integrity hooks are deactivated
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4755
diff changeset
  1458
            return self.regular_formats + tuple(NEED_PERM_FORMATS)
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
  1459
    return self.regular_formats
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1460
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1461
# XXX itou for some Statement methods
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1462
from rql import stmts
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
  1463
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
  1464
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1465
def bw_get_etype(self, name):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1466
    return orig_get_etype(self, bw_normalize_etype(name))
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
  1467
orig_get_etype = stmts.ScopeNode.get_etype
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1468
stmts.ScopeNode.get_etype = bw_get_etype
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1469
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
  1470
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1471
def bw_add_main_variable_delete(self, etype, vref):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1472
    return orig_add_main_variable_delete(self, bw_normalize_etype(etype), vref)
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
  1473
orig_add_main_variable_delete = stmts.Delete.add_main_variable
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1474
stmts.Delete.add_main_variable = bw_add_main_variable_delete
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1475
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
  1476
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1477
def bw_add_main_variable_insert(self, etype, vref):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1478
    return orig_add_main_variable_insert(self, bw_normalize_etype(etype), vref)
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
  1479
orig_add_main_variable_insert = stmts.Insert.add_main_variable
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1480
stmts.Insert.add_main_variable = bw_add_main_variable_insert
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1481
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
  1482
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1483
def bw_set_statement_type(self, etype):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1484
    return orig_set_statement_type(self, bw_normalize_etype(etype))
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11416
diff changeset
  1485
orig_set_statement_type = stmts.Select.set_statement_type
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1486
stmts.Select.set_statement_type = bw_set_statement_type