entity.py
author Sylvain Thénault <sylvain.thenault@logilab.fr>
Wed, 16 Jun 2010 14:51:17 +0200
changeset 5762 730d458ec1bf
parent 5736 375819ec7d43
parent 5757 e501806ab489
child 5797 7183f32fad13
permissions -rw-r--r--
backport stable
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
5421
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5320
diff changeset
     1
# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5320
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: 5320
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: 5320
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: 5320
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: 5320
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: 5320
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: 5320
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: 5320
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: 5320
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: 5320
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: 5320
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: 5320
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: 5320
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: 5320
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: 5320
diff changeset
    17
# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
5733
d00d1fab42af cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
    18
"""Base class for entity objects manipulated in clients"""
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    19
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    20
__docformat__ = "restructuredtext en"
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    21
5726
c3b99606644d [json] fix json serialization for recent simplejson implementation, and test encoding of entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5573
diff changeset
    22
from copy import copy
1154
9b23a6836c32 support for old __rtags__
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
    23
from warnings import warn
9b23a6836c32 support for old __rtags__
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
    24
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    25
from logilab.common import interface
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    26
from logilab.common.decorators import cached
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
    27
from logilab.common.deprecation import deprecated
2312
af4d8f75c5db use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2125
diff changeset
    28
from logilab.mtconverter import TransformData, TransformError, xml_escape
631
99f5852f8604 major selector refactoring (mostly to avoid looking for select parameters on the target class), start accept / interface unification)
sylvain.thenault@logilab.fr
parents: 479
diff changeset
    29
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    30
from rql.utils import rqlvar_maker
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    31
3664
af7ca3597b8d use typed_eid
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3626
diff changeset
    32
from cubicweb import Unauthorized, typed_eid
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    33
from cubicweb.rset import ResultSet
692
800592b8d39b replace deprecated cubicweb.common.selectors by its new module path (cubicweb.selectors)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 631
diff changeset
    34
from cubicweb.selectors import yes
2656
a93ae0f6c0ad R [base classes] only AppObject remaning, no more AppRsetObject
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
    35
from cubicweb.appobject import AppObject
4835
13b0b96d7982 [repo] enhanced security handling: deprecates unsafe_execute, in favor of explicit read/write security control using the `enabled_security` context manager. Also code executed on the repository side is now unsafe by default.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4831
diff changeset
    36
from cubicweb.req import _check_cw_unsafe
2827
d1a89d165045 remove 3.2 bw compat code
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2824
diff changeset
    37
from cubicweb.schema import RQLVocabularyConstraint, RQLConstraint
3241
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
    38
from cubicweb.rqlrewrite import RQLRewriter
709
b21ee900c732 avoid dependency to common
sylvain.thenault@logilab.fr
parents: 707
diff changeset
    39
4023
eae23c40627a drop common subpackage
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3998
diff changeset
    40
from cubicweb.uilib import printable_value, soup2xhtml
eae23c40627a drop common subpackage
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3998
diff changeset
    41
from cubicweb.mixins import MI_REL_TRIGGERS
eae23c40627a drop common subpackage
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3998
diff changeset
    42
from cubicweb.mttransforms import ENGINE
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    43
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    44
_marker = object()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    45
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    46
def greater_card(rschema, subjtypes, objtypes, index):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    47
    for subjtype in subjtypes:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    48
        for objtype in objtypes:
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
    49
            card = rschema.rdef(subjtype, objtype).cardinality[index]
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    50
            if card in '+*':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    51
                return card
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    52
    return '1'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    53
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    54
5726
c3b99606644d [json] fix json serialization for recent simplejson implementation, and test encoding of entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5573
diff changeset
    55
class Entity(AppObject):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    56
    """an entity instance has e_schema automagically set on
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    57
    the class and instances has access to their issuing cursor.
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
    58
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    59
    A property is set for each attribute and relation on each entity's type
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    60
    class. Becare that among attributes, 'eid' is *NEITHER* stored in the
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    61
    dict containment (which acts as a cache for other attributes dynamically
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    62
    fetched)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    63
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    64
    :type e_schema: `cubicweb.schema.EntitySchema`
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    65
    :ivar e_schema: the entity's schema
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    66
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    67
    :type rest_var: str
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    68
    :cvar rest_var: indicates which attribute should be used to build REST urls
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    69
                    If None is specified, the first non-meta attribute will
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    70
                    be used
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
    71
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    72
    :type skip_copy_for: list
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    73
    :cvar skip_copy_for: a list of relations that should be skipped when copying
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    74
                         this kind of entity. Note that some relations such
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    75
                         as composite relations or relations that have '?1' as object
4965
04543ed0bbdc [source] only consider edited_attributes in source.preprocess_entity()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4913
diff changeset
    76
                         cardinality are always skipped.
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    77
    """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    78
    __registry__ = 'etypes'
717
54b873918b48 kill id_registerer
sylvain.thenault@logilab.fr
parents: 714
diff changeset
    79
    __select__ = yes()
1264
fe2934a7df7f cleanup, avoid spurious warning
sylvain.thenault@logilab.fr
parents: 1177
diff changeset
    80
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
    81
    # class attributes that must be set in class definition
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    82
    rest_attr = None
1138
22f634977c95 make pylint happy, fix some bugs on the way
sylvain.thenault@logilab.fr
parents: 1132
diff changeset
    83
    fetch_attrs = None
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2877
diff changeset
    84
    skip_copy_for = ('in_state',)
1264
fe2934a7df7f cleanup, avoid spurious warning
sylvain.thenault@logilab.fr
parents: 1177
diff changeset
    85
    # class attributes set automatically at registration time
fe2934a7df7f cleanup, avoid spurious warning
sylvain.thenault@logilab.fr
parents: 1177
diff changeset
    86
    e_schema = None
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
    87
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    88
    @classmethod
2807
696ff03f9a58 __initialize__ needs the schema as argument
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2788
diff changeset
    89
    def __initialize__(cls, schema):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    90
        """initialize a specific entity class by adding descriptors to access
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    91
        entity type's attributes and relations
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    92
        """
3376
f5c69485381f [appobjects] use __regid__ instead of __id__, more explicit
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3369
diff changeset
    93
        etype = cls.__regid__
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    94
        assert etype != 'Any', etype
2807
696ff03f9a58 __initialize__ needs the schema as argument
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2788
diff changeset
    95
        cls.e_schema = eschema = schema.eschema(etype)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    96
        for rschema, _ in eschema.attribute_definitions():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    97
            if rschema.type == 'eid':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    98
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    99
            setattr(cls, rschema.type, Attribute(rschema.type))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   100
        mixins = []
2941
196493bd099c [entity] use role instead of x
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2931
diff changeset
   101
        for rschema, _, role in eschema.relation_definitions():
196493bd099c [entity] use role instead of x
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2931
diff changeset
   102
            if (rschema, role) in MI_REL_TRIGGERS:
196493bd099c [entity] use role instead of x
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2931
diff changeset
   103
                mixin = MI_REL_TRIGGERS[(rschema, role)]
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   104
                if not (issubclass(cls, mixin) or mixin in mixins): # already mixed ?
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   105
                    mixins.append(mixin)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   106
                for iface in getattr(mixin, '__implements__', ()):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   107
                    if not interface.implements(cls, iface):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   108
                        interface.extend(cls, iface)
2941
196493bd099c [entity] use role instead of x
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2931
diff changeset
   109
            if role == 'subject':
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   110
                attr = rschema.type
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   111
            else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   112
                attr = 'reverse_%s' % rschema.type
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   113
            setattr(cls, attr, Relation(rschema, role))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   114
        if mixins:
3919
f91bd15f427c fix nasty pluggable mixins bug, where mixins take precedence other user class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   115
            # see etype class instantation in cwvreg.ETypeRegistry.etype_class method:
f91bd15f427c fix nasty pluggable mixins bug, where mixins take precedence other user class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   116
            # due to class dumping, cls is the generated top level class with actual
f91bd15f427c fix nasty pluggable mixins bug, where mixins take precedence other user class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   117
            # user class as (only) parent. Since we want to be able to override mixins
f91bd15f427c fix nasty pluggable mixins bug, where mixins take precedence other user class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   118
            # method from this user class, we have to take care to insert mixins after that
f91bd15f427c fix nasty pluggable mixins bug, where mixins take precedence other user class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   119
            # class
f91bd15f427c fix nasty pluggable mixins bug, where mixins take precedence other user class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   120
            #
f91bd15f427c fix nasty pluggable mixins bug, where mixins take precedence other user class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   121
            # note that we don't plug mixins as user class parent since it causes pb
f91bd15f427c fix nasty pluggable mixins bug, where mixins take precedence other user class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   122
            # with some cases of entity classes inheritance.
f91bd15f427c fix nasty pluggable mixins bug, where mixins take precedence other user class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   123
            mixins.insert(0, cls.__bases__[0])
f91bd15f427c fix nasty pluggable mixins bug, where mixins take precedence other user class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   124
            mixins += cls.__bases__[1:]
f91bd15f427c fix nasty pluggable mixins bug, where mixins take precedence other user class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   125
            cls.__bases__ = tuple(mixins)
f91bd15f427c fix nasty pluggable mixins bug, where mixins take precedence other user class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   126
            cls.info('plugged %s mixins on %s', mixins, cls)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   127
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   128
    fetch_attrs = ('modification_date',)
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   129
    @classmethod
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   130
    def fetch_order(cls, attr, var):
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   131
        """class method used to control sort order when multiple entities of
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   132
        this type are fetched
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   133
        """
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   134
        return cls.fetch_unrelated_order(attr, var)
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   135
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   136
    @classmethod
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   137
    def fetch_unrelated_order(cls, attr, var):
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   138
        """class method used to control sort order when multiple entities of
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   139
        this type are fetched to use in edition (eg propose them to create a
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   140
        new relation on an edited entity).
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   141
        """
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   142
        if attr == 'modification_date':
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   143
            return '%s DESC' % var
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   144
        return None
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   145
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   146
    @classmethod
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   147
    def fetch_rql(cls, user, restriction=None, fetchattrs=None, mainvar='X',
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   148
                  settype=True, ordermethod='fetch_order'):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   149
        """return a rql to fetch all entities of the class type"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   150
        restrictions = restriction or []
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   151
        if settype:
3376
f5c69485381f [appobjects] use __regid__ instead of __id__, more explicit
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3369
diff changeset
   152
            restrictions.append('%s is %s' % (mainvar, cls.__regid__))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   153
        if fetchattrs is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   154
            fetchattrs = cls.fetch_attrs
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   155
        selection = [mainvar]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   156
        orderby = []
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   157
        # start from 26 to avoid possible conflicts with X
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   158
        varmaker = rqlvar_maker(index=26)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   159
        cls._fetch_restrictions(mainvar, varmaker, fetchattrs, selection,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   160
                                orderby, restrictions, user, ordermethod)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   161
        rql = 'Any %s' % ','.join(selection)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   162
        if orderby:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   163
            rql +=  ' ORDERBY %s' % ','.join(orderby)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   164
        rql += ' WHERE %s' % ', '.join(restrictions)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   165
        return rql
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   166
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   167
    @classmethod
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   168
    def _fetch_restrictions(cls, mainvar, varmaker, fetchattrs,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   169
                            selection, orderby, restrictions, user,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   170
                            ordermethod='fetch_order', visited=None):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   171
        eschema = cls.e_schema
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   172
        if visited is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   173
            visited = set((eschema.type,))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   174
        elif eschema.type in visited:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   175
            # avoid infinite recursion
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   176
            return
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   177
        else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   178
            visited.add(eschema.type)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   179
        _fetchattrs = []
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   180
        for attr in fetchattrs:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   181
            try:
3689
deb13e88e037 follow yams 0.25 api changes to improve performance
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3683
diff changeset
   182
                rschema = eschema.subjrels[attr]
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   183
            except KeyError:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   184
                cls.warning('skipping fetch_attr %s defined in %s (not found in schema)',
3376
f5c69485381f [appobjects] use __regid__ instead of __id__, more explicit
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3369
diff changeset
   185
                            attr, cls.__regid__)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   186
                continue
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   187
            rdef = eschema.rdef(attr)
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   188
            if not user.matching_groups(rdef.get_groups('read')):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   189
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   190
            var = varmaker.next()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   191
            selection.append(var)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   192
            restriction = '%s %s %s' % (mainvar, attr, var)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   193
            restrictions.append(restriction)
3689
deb13e88e037 follow yams 0.25 api changes to improve performance
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3683
diff changeset
   194
            if not rschema.final:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   195
                # XXX this does not handle several destination types
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   196
                desttype = rschema.objects(eschema.type)[0]
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   197
                card = rdef.cardinality[0]
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   198
                if card not in '?1':
2928
edfdb69df6e8 oops, not self but cls here
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2877
diff changeset
   199
                    cls.warning('bad relation %s specified in fetch attrs for %s',
edfdb69df6e8 oops, not self but cls here
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2877
diff changeset
   200
                                 attr, cls)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   201
                    selection.pop()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   202
                    restrictions.pop()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   203
                    continue
2871
83c5499e1436 [entity] fix fetch_rql w/ case where it's called while entity is not 'complete' (eg time where it's being added but have not yet all mandatory relations set)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2658
diff changeset
   204
                # XXX we need outer join in case the relation is not mandatory
83c5499e1436 [entity] fix fetch_rql w/ case where it's called while entity is not 'complete' (eg time where it's being added but have not yet all mandatory relations set)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2658
diff changeset
   205
                # (card == '?')  *or if the entity is being added*, since in
83c5499e1436 [entity] fix fetch_rql w/ case where it's called while entity is not 'complete' (eg time where it's being added but have not yet all mandatory relations set)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2658
diff changeset
   206
                # that case the relation may still be missing. As we miss this
83c5499e1436 [entity] fix fetch_rql w/ case where it's called while entity is not 'complete' (eg time where it's being added but have not yet all mandatory relations set)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2658
diff changeset
   207
                # later information here, systematically add it.
83c5499e1436 [entity] fix fetch_rql w/ case where it's called while entity is not 'complete' (eg time where it's being added but have not yet all mandatory relations set)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2658
diff changeset
   208
                restrictions[-1] += '?'
4049
5838a4b0766d 3.5 api update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4023
diff changeset
   209
                # XXX user._cw.vreg iiiirk
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   210
                destcls = user._cw.vreg['etypes'].etype_class(desttype)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   211
                destcls._fetch_restrictions(var, varmaker, destcls.fetch_attrs,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   212
                                            selection, orderby, restrictions,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   213
                                            user, ordermethod, visited=visited)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   214
            orderterm = getattr(cls, ordermethod)(attr, var)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   215
            if orderterm:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   216
                orderby.append(orderterm)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   217
        return selection, orderby, restrictions
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   218
1471
c889c3bcf5ec new parent_classes method (cached)
sylvain.thenault@logilab.fr
parents: 1435
diff changeset
   219
    @classmethod
c889c3bcf5ec new parent_classes method (cached)
sylvain.thenault@logilab.fr
parents: 1435
diff changeset
   220
    @cached
1840
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   221
    def _rest_attr_info(cls):
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   222
        mainattr, needcheck = 'eid', True
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   223
        if cls.rest_attr:
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   224
            mainattr = cls.rest_attr
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   225
            needcheck = not cls.e_schema.has_unique_values(mainattr)
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   226
        else:
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   227
            for rschema in cls.e_schema.subject_relations():
3689
deb13e88e037 follow yams 0.25 api changes to improve performance
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3683
diff changeset
   228
                if rschema.final and rschema != 'eid' and cls.e_schema.has_unique_values(rschema):
1840
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   229
                    mainattr = str(rschema)
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   230
                    needcheck = False
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   231
                    break
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   232
        if mainattr == 'eid':
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   233
            needcheck = False
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   234
        return mainattr, needcheck
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   235
5199
ebb50479d2ab [entity] move req.create_entity content to a cw_instantiate factory method on entity classes, so cube developpers will be able to easily customize instance creation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   236
    @classmethod
ebb50479d2ab [entity] move req.create_entity content to a cw_instantiate factory method on entity classes, so cube developpers will be able to easily customize instance creation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   237
    def cw_instantiate(cls, execute, **kwargs):
ebb50479d2ab [entity] move req.create_entity content to a cw_instantiate factory method on entity classes, so cube developpers will be able to easily customize instance creation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   238
        """add a new entity of this given type
ebb50479d2ab [entity] move req.create_entity content to a cw_instantiate factory method on entity classes, so cube developpers will be able to easily customize instance creation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   239
ebb50479d2ab [entity] move req.create_entity content to a cw_instantiate factory method on entity classes, so cube developpers will be able to easily customize instance creation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   240
        Example (in a shell session):
ebb50479d2ab [entity] move req.create_entity content to a cw_instantiate factory method on entity classes, so cube developpers will be able to easily customize instance creation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   241
ebb50479d2ab [entity] move req.create_entity content to a cw_instantiate factory method on entity classes, so cube developpers will be able to easily customize instance creation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   242
        >>> companycls = vreg['etypes'].etype_class(('Company')
ebb50479d2ab [entity] move req.create_entity content to a cw_instantiate factory method on entity classes, so cube developpers will be able to easily customize instance creation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   243
        >>> personcls = vreg['etypes'].etype_class(('Person')
ebb50479d2ab [entity] move req.create_entity content to a cw_instantiate factory method on entity classes, so cube developpers will be able to easily customize instance creation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   244
        >>> c = companycls.cw_instantiate(req.execute, name=u'Logilab')
ebb50479d2ab [entity] move req.create_entity content to a cw_instantiate factory method on entity classes, so cube developpers will be able to easily customize instance creation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   245
        >>> personcls.cw_instantiate(req.execute, firstname=u'John', lastname=u'Doe',
ebb50479d2ab [entity] move req.create_entity content to a cw_instantiate factory method on entity classes, so cube developpers will be able to easily customize instance creation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   246
        ...                          works_for=c)
ebb50479d2ab [entity] move req.create_entity content to a cw_instantiate factory method on entity classes, so cube developpers will be able to easily customize instance creation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   247
ebb50479d2ab [entity] move req.create_entity content to a cw_instantiate factory method on entity classes, so cube developpers will be able to easily customize instance creation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   248
        """
ebb50479d2ab [entity] move req.create_entity content to a cw_instantiate factory method on entity classes, so cube developpers will be able to easily customize instance creation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   249
        rql = 'INSERT %s X' % cls.__regid__
ebb50479d2ab [entity] move req.create_entity content to a cw_instantiate factory method on entity classes, so cube developpers will be able to easily customize instance creation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   250
        relations = []
ebb50479d2ab [entity] move req.create_entity content to a cw_instantiate factory method on entity classes, so cube developpers will be able to easily customize instance creation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   251
        restrictions = set()
ebb50479d2ab [entity] move req.create_entity content to a cw_instantiate factory method on entity classes, so cube developpers will be able to easily customize instance creation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   252
        pending_relations = []
ebb50479d2ab [entity] move req.create_entity content to a cw_instantiate factory method on entity classes, so cube developpers will be able to easily customize instance creation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   253
        for attr, value in kwargs.items():
ebb50479d2ab [entity] move req.create_entity content to a cw_instantiate factory method on entity classes, so cube developpers will be able to easily customize instance creation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   254
            if isinstance(value, (tuple, list, set, frozenset)):
ebb50479d2ab [entity] move req.create_entity content to a cw_instantiate factory method on entity classes, so cube developpers will be able to easily customize instance creation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   255
                if len(value) == 1:
ebb50479d2ab [entity] move req.create_entity content to a cw_instantiate factory method on entity classes, so cube developpers will be able to easily customize instance creation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   256
                    value = iter(value).next()
ebb50479d2ab [entity] move req.create_entity content to a cw_instantiate factory method on entity classes, so cube developpers will be able to easily customize instance creation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   257
                else:
ebb50479d2ab [entity] move req.create_entity content to a cw_instantiate factory method on entity classes, so cube developpers will be able to easily customize instance creation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   258
                    del kwargs[attr]
ebb50479d2ab [entity] move req.create_entity content to a cw_instantiate factory method on entity classes, so cube developpers will be able to easily customize instance creation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   259
                    pending_relations.append( (attr, value) )
ebb50479d2ab [entity] move req.create_entity content to a cw_instantiate factory method on entity classes, so cube developpers will be able to easily customize instance creation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   260
                    continue
ebb50479d2ab [entity] move req.create_entity content to a cw_instantiate factory method on entity classes, so cube developpers will be able to easily customize instance creation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   261
            if hasattr(value, 'eid'): # non final relation
ebb50479d2ab [entity] move req.create_entity content to a cw_instantiate factory method on entity classes, so cube developpers will be able to easily customize instance creation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   262
                rvar = attr.upper()
ebb50479d2ab [entity] move req.create_entity content to a cw_instantiate factory method on entity classes, so cube developpers will be able to easily customize instance creation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   263
                # XXX safer detection of object relation
ebb50479d2ab [entity] move req.create_entity content to a cw_instantiate factory method on entity classes, so cube developpers will be able to easily customize instance creation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   264
                if attr.startswith('reverse_'):
ebb50479d2ab [entity] move req.create_entity content to a cw_instantiate factory method on entity classes, so cube developpers will be able to easily customize instance creation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   265
                    relations.append('%s %s X' % (rvar, attr[len('reverse_'):]))
ebb50479d2ab [entity] move req.create_entity content to a cw_instantiate factory method on entity classes, so cube developpers will be able to easily customize instance creation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   266
                else:
ebb50479d2ab [entity] move req.create_entity content to a cw_instantiate factory method on entity classes, so cube developpers will be able to easily customize instance creation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   267
                    relations.append('X %s %s' % (attr, rvar))
ebb50479d2ab [entity] move req.create_entity content to a cw_instantiate factory method on entity classes, so cube developpers will be able to easily customize instance creation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   268
                restriction = '%s eid %%(%s)s' % (rvar, attr)
ebb50479d2ab [entity] move req.create_entity content to a cw_instantiate factory method on entity classes, so cube developpers will be able to easily customize instance creation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   269
                if not restriction in restrictions:
ebb50479d2ab [entity] move req.create_entity content to a cw_instantiate factory method on entity classes, so cube developpers will be able to easily customize instance creation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   270
                    restrictions.add(restriction)
ebb50479d2ab [entity] move req.create_entity content to a cw_instantiate factory method on entity classes, so cube developpers will be able to easily customize instance creation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   271
                kwargs[attr] = value.eid
ebb50479d2ab [entity] move req.create_entity content to a cw_instantiate factory method on entity classes, so cube developpers will be able to easily customize instance creation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   272
            else: # attribute
ebb50479d2ab [entity] move req.create_entity content to a cw_instantiate factory method on entity classes, so cube developpers will be able to easily customize instance creation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   273
                relations.append('X %s %%(%s)s' % (attr, attr))
ebb50479d2ab [entity] move req.create_entity content to a cw_instantiate factory method on entity classes, so cube developpers will be able to easily customize instance creation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   274
        if relations:
ebb50479d2ab [entity] move req.create_entity content to a cw_instantiate factory method on entity classes, so cube developpers will be able to easily customize instance creation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   275
            rql = '%s: %s' % (rql, ', '.join(relations))
ebb50479d2ab [entity] move req.create_entity content to a cw_instantiate factory method on entity classes, so cube developpers will be able to easily customize instance creation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   276
        if restrictions:
ebb50479d2ab [entity] move req.create_entity content to a cw_instantiate factory method on entity classes, so cube developpers will be able to easily customize instance creation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   277
            rql = '%s WHERE %s' % (rql, ', '.join(restrictions))
ebb50479d2ab [entity] move req.create_entity content to a cw_instantiate factory method on entity classes, so cube developpers will be able to easily customize instance creation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   278
        created = execute(rql, kwargs).get_entity(0, 0)
ebb50479d2ab [entity] move req.create_entity content to a cw_instantiate factory method on entity classes, so cube developpers will be able to easily customize instance creation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   279
        for attr, values in pending_relations:
ebb50479d2ab [entity] move req.create_entity content to a cw_instantiate factory method on entity classes, so cube developpers will be able to easily customize instance creation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   280
            if attr.startswith('reverse_'):
ebb50479d2ab [entity] move req.create_entity content to a cw_instantiate factory method on entity classes, so cube developpers will be able to easily customize instance creation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   281
                restr = 'Y %s X' % attr[len('reverse_'):]
ebb50479d2ab [entity] move req.create_entity content to a cw_instantiate factory method on entity classes, so cube developpers will be able to easily customize instance creation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   282
            else:
ebb50479d2ab [entity] move req.create_entity content to a cw_instantiate factory method on entity classes, so cube developpers will be able to easily customize instance creation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   283
                restr = 'X %s Y' % attr
ebb50479d2ab [entity] move req.create_entity content to a cw_instantiate factory method on entity classes, so cube developpers will be able to easily customize instance creation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   284
            execute('SET %s WHERE X eid %%(x)s, Y eid IN (%s)' % (
ebb50479d2ab [entity] move req.create_entity content to a cw_instantiate factory method on entity classes, so cube developpers will be able to easily customize instance creation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   285
                restr, ','.join(str(r.eid) for r in values)),
ebb50479d2ab [entity] move req.create_entity content to a cw_instantiate factory method on entity classes, so cube developpers will be able to easily customize instance creation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   286
                    {'x': created.eid}, build_descr=False)
ebb50479d2ab [entity] move req.create_entity content to a cw_instantiate factory method on entity classes, so cube developpers will be able to easily customize instance creation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   287
        return created
ebb50479d2ab [entity] move req.create_entity content to a cw_instantiate factory method on entity classes, so cube developpers will be able to easily customize instance creation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   288
1435
6cd6172718bb allow to instantiate an entity without rset
sylvain.thenault@logilab.fr
parents: 1363
diff changeset
   289
    def __init__(self, req, rset=None, row=None, col=0):
2822
f26578339214 deprecate appobject.vreg and rename appobject instance attributes using cw_ prefix
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2818
diff changeset
   290
        AppObject.__init__(self, req, rset=rset, row=row, col=col)
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   291
        self._cw_related_cache = {}
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   292
        if rset is not None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   293
            self.eid = rset[row][col]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   294
        else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   295
            self.eid = None
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   296
        self._cw_is_saved = True
5726
c3b99606644d [json] fix json serialization for recent simplejson implementation, and test encoding of entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5573
diff changeset
   297
        self.cw_attr_cache = {}
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   298
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   299
    def __repr__(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   300
        return '<Entity %s %s %s at %s>' % (
5726
c3b99606644d [json] fix json serialization for recent simplejson implementation, and test encoding of entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5573
diff changeset
   301
            self.e_schema, self.eid, self.cw_attr_cache.keys(), id(self))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   302
5320
848e92bb81cc [json] provide a custom json encoder for entities that includes eid in the json object
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 5199
diff changeset
   303
    def __json_encode__(self):
848e92bb81cc [json] provide a custom json encoder for entities that includes eid in the json object
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 5199
diff changeset
   304
        """custom json dumps hook to dump the entity's eid
848e92bb81cc [json] provide a custom json encoder for entities that includes eid in the json object
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 5199
diff changeset
   305
        which is not part of dict structure itself
848e92bb81cc [json] provide a custom json encoder for entities that includes eid in the json object
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 5199
diff changeset
   306
        """
848e92bb81cc [json] provide a custom json encoder for entities that includes eid in the json object
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 5199
diff changeset
   307
        dumpable = dict(self)
848e92bb81cc [json] provide a custom json encoder for entities that includes eid in the json object
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 5199
diff changeset
   308
        dumpable['eid'] = self.eid
848e92bb81cc [json] provide a custom json encoder for entities that includes eid in the json object
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 5199
diff changeset
   309
        return dumpable
848e92bb81cc [json] provide a custom json encoder for entities that includes eid in the json object
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 5199
diff changeset
   310
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   311
    def __nonzero__(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   312
        return True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   313
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   314
    def __hash__(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   315
        return id(self)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   316
3047
ba86b1bdbcab fix __cmp__ arguments
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3000
diff changeset
   317
    def __cmp__(self, other):
3000
4e76477949d5 B [entities] #343385 comparing entities should raise NotImplementedError
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2928
diff changeset
   318
        raise NotImplementedError('comparison not implemented for %s' % self.__class__)
4e76477949d5 B [entities] #343385 comparing entities should raise NotImplementedError
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2928
diff changeset
   319
5726
c3b99606644d [json] fix json serialization for recent simplejson implementation, and test encoding of entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5573
diff changeset
   320
    def __contains__(self, key):
c3b99606644d [json] fix json serialization for recent simplejson implementation, and test encoding of entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5573
diff changeset
   321
        return key in self.cw_attr_cache
c3b99606644d [json] fix json serialization for recent simplejson implementation, and test encoding of entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5573
diff changeset
   322
c3b99606644d [json] fix json serialization for recent simplejson implementation, and test encoding of entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5573
diff changeset
   323
    def __iter__(self):
c3b99606644d [json] fix json serialization for recent simplejson implementation, and test encoding of entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5573
diff changeset
   324
        return iter(self.cw_attr_cache)
c3b99606644d [json] fix json serialization for recent simplejson implementation, and test encoding of entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5573
diff changeset
   325
4970
1f3d8946ea84 fix security issue introduced by 4967:04543ed0bbdc: attributes explicitly set by hooks should not be checked by security hooks
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4965
diff changeset
   326
    def __getitem__(self, key):
1f3d8946ea84 fix security issue introduced by 4967:04543ed0bbdc: attributes explicitly set by hooks should not be checked by security hooks
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4965
diff changeset
   327
        if key == 'eid':
1f3d8946ea84 fix security issue introduced by 4967:04543ed0bbdc: attributes explicitly set by hooks should not be checked by security hooks
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4965
diff changeset
   328
            warn('[3.7] entity["eid"] is deprecated, use entity.eid instead',
1f3d8946ea84 fix security issue introduced by 4967:04543ed0bbdc: attributes explicitly set by hooks should not be checked by security hooks
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4965
diff changeset
   329
                 DeprecationWarning, stacklevel=2)
1f3d8946ea84 fix security issue introduced by 4967:04543ed0bbdc: attributes explicitly set by hooks should not be checked by security hooks
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4965
diff changeset
   330
            return self.eid
5726
c3b99606644d [json] fix json serialization for recent simplejson implementation, and test encoding of entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5573
diff changeset
   331
        return self.cw_attr_cache[key]
4970
1f3d8946ea84 fix security issue introduced by 4967:04543ed0bbdc: attributes explicitly set by hooks should not be checked by security hooks
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4965
diff changeset
   332
4965
04543ed0bbdc [source] only consider edited_attributes in source.preprocess_entity()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4913
diff changeset
   333
    def __setitem__(self, attr, value):
04543ed0bbdc [source] only consider edited_attributes in source.preprocess_entity()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4913
diff changeset
   334
        """override __setitem__ to update self.edited_attributes.
04543ed0bbdc [source] only consider edited_attributes in source.preprocess_entity()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4913
diff changeset
   335
4989
0e6dca27422c [repo entity] we have to provide a __delitem__ implementation as well, see example in the docstring
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4988
diff changeset
   336
        Typically, a before_[update|add]_hook could do::
4965
04543ed0bbdc [source] only consider edited_attributes in source.preprocess_entity()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4913
diff changeset
   337
04543ed0bbdc [source] only consider edited_attributes in source.preprocess_entity()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4913
diff changeset
   338
            entity['generated_attr'] = generated_value
04543ed0bbdc [source] only consider edited_attributes in source.preprocess_entity()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4913
diff changeset
   339
4989
0e6dca27422c [repo entity] we have to provide a __delitem__ implementation as well, see example in the docstring
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4988
diff changeset
   340
        and this way, edited_attributes will be updated accordingly. Also, add
0e6dca27422c [repo entity] we have to provide a __delitem__ implementation as well, see example in the docstring
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4988
diff changeset
   341
        the attribute to skip_security since we don't want to check security
0e6dca27422c [repo entity] we have to provide a __delitem__ implementation as well, see example in the docstring
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4988
diff changeset
   342
        for such attributes set by hooks.
4965
04543ed0bbdc [source] only consider edited_attributes in source.preprocess_entity()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4913
diff changeset
   343
        """
04543ed0bbdc [source] only consider edited_attributes in source.preprocess_entity()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4913
diff changeset
   344
        if attr == 'eid':
04543ed0bbdc [source] only consider edited_attributes in source.preprocess_entity()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4913
diff changeset
   345
            warn('[3.7] entity["eid"] = value is deprecated, use entity.eid = value instead',
04543ed0bbdc [source] only consider edited_attributes in source.preprocess_entity()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4913
diff changeset
   346
                 DeprecationWarning, stacklevel=2)
04543ed0bbdc [source] only consider edited_attributes in source.preprocess_entity()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4913
diff changeset
   347
            self.eid = value
04543ed0bbdc [source] only consider edited_attributes in source.preprocess_entity()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4913
diff changeset
   348
        else:
5726
c3b99606644d [json] fix json serialization for recent simplejson implementation, and test encoding of entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5573
diff changeset
   349
            self.cw_attr_cache[attr] = value
4990
3bf481cf51cb [security] don't add attribute into skip_security if already in edited_attributes, else we may accidentaly skip a desired security check
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4989
diff changeset
   350
            # don't add attribute into skip_security if already in edited
3bf481cf51cb [security] don't add attribute into skip_security if already in edited_attributes, else we may accidentaly skip a desired security check
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4989
diff changeset
   351
            # attributes, else we may accidentaly skip a desired security check
3bf481cf51cb [security] don't add attribute into skip_security if already in edited_attributes, else we may accidentaly skip a desired security check
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4989
diff changeset
   352
            if hasattr(self, 'edited_attributes') and \
3bf481cf51cb [security] don't add attribute into skip_security if already in edited_attributes, else we may accidentaly skip a desired security check
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4989
diff changeset
   353
                   attr not in self.edited_attributes:
4965
04543ed0bbdc [source] only consider edited_attributes in source.preprocess_entity()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4913
diff changeset
   354
                self.edited_attributes.add(attr)
5559
6b183d860295 [entity] fix access to attribute which has been renamed two revisions ago
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5557
diff changeset
   355
                self._cw_skip_security_attributes.add(attr)
4965
04543ed0bbdc [source] only consider edited_attributes in source.preprocess_entity()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4913
diff changeset
   356
4989
0e6dca27422c [repo entity] we have to provide a __delitem__ implementation as well, see example in the docstring
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4988
diff changeset
   357
    def __delitem__(self, attr):
0e6dca27422c [repo entity] we have to provide a __delitem__ implementation as well, see example in the docstring
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4988
diff changeset
   358
        """override __delitem__ to update self.edited_attributes on cleanup of
0e6dca27422c [repo entity] we have to provide a __delitem__ implementation as well, see example in the docstring
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4988
diff changeset
   359
        undesired changes introduced in the entity's dict. For example, see the
0e6dca27422c [repo entity] we have to provide a __delitem__ implementation as well, see example in the docstring
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4988
diff changeset
   360
        code snippet below from the `forge` cube:
0e6dca27422c [repo entity] we have to provide a __delitem__ implementation as well, see example in the docstring
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4988
diff changeset
   361
0e6dca27422c [repo entity] we have to provide a __delitem__ implementation as well, see example in the docstring
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4988
diff changeset
   362
        .. sourcecode:: python
0e6dca27422c [repo entity] we have to provide a __delitem__ implementation as well, see example in the docstring
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4988
diff changeset
   363
0e6dca27422c [repo entity] we have to provide a __delitem__ implementation as well, see example in the docstring
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4988
diff changeset
   364
            edited = self.entity.edited_attributes
0e6dca27422c [repo entity] we have to provide a __delitem__ implementation as well, see example in the docstring
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4988
diff changeset
   365
            has_load_left = 'load_left' in edited
0e6dca27422c [repo entity] we have to provide a __delitem__ implementation as well, see example in the docstring
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4988
diff changeset
   366
            if 'load' in edited and self.entity.load_left is None:
0e6dca27422c [repo entity] we have to provide a __delitem__ implementation as well, see example in the docstring
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4988
diff changeset
   367
                self.entity.load_left = self.entity['load']
0e6dca27422c [repo entity] we have to provide a __delitem__ implementation as well, see example in the docstring
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4988
diff changeset
   368
            elif not has_load_left and edited:
0e6dca27422c [repo entity] we have to provide a __delitem__ implementation as well, see example in the docstring
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4988
diff changeset
   369
                # cleanup, this may cause undesired changes
0e6dca27422c [repo entity] we have to provide a __delitem__ implementation as well, see example in the docstring
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4988
diff changeset
   370
                del self.entity['load_left']
0e6dca27422c [repo entity] we have to provide a __delitem__ implementation as well, see example in the docstring
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4988
diff changeset
   371
0e6dca27422c [repo entity] we have to provide a __delitem__ implementation as well, see example in the docstring
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4988
diff changeset
   372
        """
5726
c3b99606644d [json] fix json serialization for recent simplejson implementation, and test encoding of entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5573
diff changeset
   373
        del self.cw_attr_cache[attr]
4989
0e6dca27422c [repo entity] we have to provide a __delitem__ implementation as well, see example in the docstring
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4988
diff changeset
   374
        if hasattr(self, 'edited_attributes'):
0e6dca27422c [repo entity] we have to provide a __delitem__ implementation as well, see example in the docstring
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4988
diff changeset
   375
            self.edited_attributes.remove(attr)
0e6dca27422c [repo entity] we have to provide a __delitem__ implementation as well, see example in the docstring
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4988
diff changeset
   376
5728
12d3da7b3bcf [entity] add .clear() for bw compat
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5726
diff changeset
   377
    def clear(self):
12d3da7b3bcf [entity] add .clear() for bw compat
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5726
diff changeset
   378
        self.cw_attr_cache.clear()
12d3da7b3bcf [entity] add .clear() for bw compat
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5726
diff changeset
   379
5726
c3b99606644d [json] fix json serialization for recent simplejson implementation, and test encoding of entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5573
diff changeset
   380
    def get(self, key, default=None):
c3b99606644d [json] fix json serialization for recent simplejson implementation, and test encoding of entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5573
diff changeset
   381
        return self.cw_attr_cache.get(key, default)
c3b99606644d [json] fix json serialization for recent simplejson implementation, and test encoding of entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5573
diff changeset
   382
4970
1f3d8946ea84 fix security issue introduced by 4967:04543ed0bbdc: attributes explicitly set by hooks should not be checked by security hooks
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4965
diff changeset
   383
    def setdefault(self, attr, default):
1f3d8946ea84 fix security issue introduced by 4967:04543ed0bbdc: attributes explicitly set by hooks should not be checked by security hooks
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4965
diff changeset
   384
        """override setdefault to update self.edited_attributes"""
5726
c3b99606644d [json] fix json serialization for recent simplejson implementation, and test encoding of entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5573
diff changeset
   385
        self.cw_attr_cache.setdefault(attr, default)
4990
3bf481cf51cb [security] don't add attribute into skip_security if already in edited_attributes, else we may accidentaly skip a desired security check
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4989
diff changeset
   386
        # don't add attribute into skip_security if already in edited
3bf481cf51cb [security] don't add attribute into skip_security if already in edited_attributes, else we may accidentaly skip a desired security check
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4989
diff changeset
   387
        # attributes, else we may accidentaly skip a desired security check
3bf481cf51cb [security] don't add attribute into skip_security if already in edited_attributes, else we may accidentaly skip a desired security check
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4989
diff changeset
   388
        if hasattr(self, 'edited_attributes') and \
3bf481cf51cb [security] don't add attribute into skip_security if already in edited_attributes, else we may accidentaly skip a desired security check
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4989
diff changeset
   389
               attr not in self.edited_attributes:
4970
1f3d8946ea84 fix security issue introduced by 4967:04543ed0bbdc: attributes explicitly set by hooks should not be checked by security hooks
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4965
diff changeset
   390
            self.edited_attributes.add(attr)
5559
6b183d860295 [entity] fix access to attribute which has been renamed two revisions ago
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5557
diff changeset
   391
            self._cw_skip_security_attributes.add(attr)
4965
04543ed0bbdc [source] only consider edited_attributes in source.preprocess_entity()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4913
diff changeset
   392
5009
2ac04bc976c3 [entity] we also have to override dict.pop to properly maintain edited_attributes consistency
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4991
diff changeset
   393
    def pop(self, attr, default=_marker):
2ac04bc976c3 [entity] we also have to override dict.pop to properly maintain edited_attributes consistency
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4991
diff changeset
   394
        """override pop to update self.edited_attributes on cleanup of
2ac04bc976c3 [entity] we also have to override dict.pop to properly maintain edited_attributes consistency
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4991
diff changeset
   395
        undesired changes introduced in the entity's dict. See `__delitem__`
2ac04bc976c3 [entity] we also have to override dict.pop to properly maintain edited_attributes consistency
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4991
diff changeset
   396
        """
2ac04bc976c3 [entity] we also have to override dict.pop to properly maintain edited_attributes consistency
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4991
diff changeset
   397
        if default is _marker:
5726
c3b99606644d [json] fix json serialization for recent simplejson implementation, and test encoding of entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5573
diff changeset
   398
            value = self.cw_attr_cache.pop(attr)
5009
2ac04bc976c3 [entity] we also have to override dict.pop to properly maintain edited_attributes consistency
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4991
diff changeset
   399
        else:
5726
c3b99606644d [json] fix json serialization for recent simplejson implementation, and test encoding of entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5573
diff changeset
   400
            value = self.cw_attr_cache.pop(attr, default)
5009
2ac04bc976c3 [entity] we also have to override dict.pop to properly maintain edited_attributes consistency
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4991
diff changeset
   401
        if hasattr(self, 'edited_attributes') and attr in self.edited_attributes:
2ac04bc976c3 [entity] we also have to override dict.pop to properly maintain edited_attributes consistency
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4991
diff changeset
   402
            self.edited_attributes.remove(attr)
2ac04bc976c3 [entity] we also have to override dict.pop to properly maintain edited_attributes consistency
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4991
diff changeset
   403
        return value
2ac04bc976c3 [entity] we also have to override dict.pop to properly maintain edited_attributes consistency
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4991
diff changeset
   404
5115
2e43ef618d14 [repository] forbid usage of set_attributes() in before_add_entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5009
diff changeset
   405
    def update(self, values):
2e43ef618d14 [repository] forbid usage of set_attributes() in before_add_entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5009
diff changeset
   406
        """override update to update self.edited_attributes. See `__setitem__`
2e43ef618d14 [repository] forbid usage of set_attributes() in before_add_entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5009
diff changeset
   407
        """
2e43ef618d14 [repository] forbid usage of set_attributes() in before_add_entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5009
diff changeset
   408
        for attr, value in values.items():
2e43ef618d14 [repository] forbid usage of set_attributes() in before_add_entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5009
diff changeset
   409
            self[attr] = value # use self.__setitem__ implementation
2e43ef618d14 [repository] forbid usage of set_attributes() in before_add_entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5009
diff changeset
   410
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   411
    def cw_adapt_to(self, interface):
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   412
        """return an adapter the entity to the given interface name.
4965
04543ed0bbdc [source] only consider edited_attributes in source.preprocess_entity()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4913
diff changeset
   413
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   414
        return None if it can not be adapted.
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   415
        """
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   416
        try:
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   417
            cache = self._cw_adapters_cache
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   418
        except AttributeError:
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   419
            self._cw_adapters_cache = cache = {}
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   420
        try:
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   421
            return cache[interface]
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   422
        except KeyError:
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   423
            adapter = self._cw.vreg['adapters'].select_or_none(
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   424
                interface, self._cw, entity=self)
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   425
            cache[interface] = adapter
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   426
            return adapter
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   427
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   428
    def has_eid(self): # XXX cw_has_eid
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   429
        """return True if the entity has an attributed eid (False
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   430
        meaning that the entity has to be created
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   431
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   432
        try:
3664
af7ca3597b8d use typed_eid
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3626
diff changeset
   433
            typed_eid(self.eid)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   434
            return True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   435
        except (ValueError, TypeError):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   436
            return False
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   437
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   438
    def cw_is_saved(self):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   439
        """during entity creation, there is some time during which the entity
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   440
        has an eid attributed though it's not saved (eg during
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   441
        'before_add_entity' hooks). You can use this method to ensure the entity
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   442
        has an eid *and* is saved in its source.
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   443
        """
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   444
        return self.has_eid() and self._cw_is_saved
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   445
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   446
    @cached
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   447
    def cw_metainformation(self):
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   448
        res = dict(zip(('type', 'source', 'extid'), self._cw.describe(self.eid)))
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   449
        res['source'] = self._cw.source_defs()[res['source']]
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   450
        return res
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   451
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   452
    def cw_check_perm(self, action):
3890
d7a270f50f54 backport stable branch (one more time painfully)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3777 3877
diff changeset
   453
        self.e_schema.check_perm(self._cw, action, eid=self.eid)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   454
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   455
    def cw_has_perm(self, action):
3890
d7a270f50f54 backport stable branch (one more time painfully)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3777 3877
diff changeset
   456
        return self.e_schema.has_perm(self._cw, action, eid=self.eid)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   457
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   458
    def view(self, __vid, __registry='views', w=None, **kwargs): # XXX cw_view
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   459
        """shortcut to apply a view on this entity"""
4451
65f4665233e6 misc typos found on my way: NameError / SyntaxError / double __select__, <sigh ...>
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4436
diff changeset
   460
        view = self._cw.vreg[__registry].select(__vid, self._cw, rset=self.cw_rset,
3459
e134d2dd9992 [entity] pass cw_row and cw_col to select(vid, ...) in self.view
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3452
diff changeset
   461
                                                row=self.cw_row, col=self.cw_col,
e134d2dd9992 [entity] pass cw_row and cw_col to select(vid, ...) in self.view
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3452
diff changeset
   462
                                                **kwargs)
5522
6be95896d49e [entity] avoid getting w in cw_extra_kwargs when calling .view
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   463
        return view.render(row=self.cw_row, col=self.cw_col, w=w, **kwargs)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   464
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   465
    def absolute_url(self, *args, **kwargs): # XXX cw_url
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   466
        """return an absolute url to view this entity"""
2059
af33833d7571 absolute_url / build_url refactoring to avoid potential name clash
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2058
diff changeset
   467
        # use *args since we don't want first argument to be "anonymous" to
af33833d7571 absolute_url / build_url refactoring to avoid potential name clash
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2058
diff changeset
   468
        # avoid potential clash with kwargs
af33833d7571 absolute_url / build_url refactoring to avoid potential name clash
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2058
diff changeset
   469
        if args:
af33833d7571 absolute_url / build_url refactoring to avoid potential name clash
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2058
diff changeset
   470
            assert len(args) == 1, 'only 0 or 1 non-named-argument expected'
af33833d7571 absolute_url / build_url refactoring to avoid potential name clash
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2058
diff changeset
   471
            method = args[0]
af33833d7571 absolute_url / build_url refactoring to avoid potential name clash
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2058
diff changeset
   472
        else:
af33833d7571 absolute_url / build_url refactoring to avoid potential name clash
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2058
diff changeset
   473
            method = None
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   474
        # in linksearch mode, we don't want external urls else selecting
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   475
        # the object for use in the relation is tricky
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   476
        # XXX search_state is web specific
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   477
        if getattr(self._cw, 'search_state', ('normal',))[0] == 'normal':
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   478
            kwargs['base_url'] = self.cw_metainformation()['source'].get('base-url')
1904
e23536d29231 minor refactoring of absolute_url()
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 1842
diff changeset
   479
        if method in (None, 'view'):
1842
c7a22540d6f7 add some bw compat code for old rest_path prototype
sylvain.thenault@logilab.fr
parents: 1840
diff changeset
   480
            try:
c7a22540d6f7 add some bw compat code for old rest_path prototype
sylvain.thenault@logilab.fr
parents: 1840
diff changeset
   481
                kwargs['_restpath'] = self.rest_path(kwargs.get('base_url'))
c7a22540d6f7 add some bw compat code for old rest_path prototype
sylvain.thenault@logilab.fr
parents: 1840
diff changeset
   482
            except TypeError:
3405
9d31c9cb8103 nicer deprecation warnings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3382
diff changeset
   483
                warn('[3.4] %s: rest_path() now take use_ext_eid argument, '
3376
f5c69485381f [appobjects] use __regid__ instead of __id__, more explicit
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3369
diff changeset
   484
                     'please update' % self.__regid__, DeprecationWarning)
1842
c7a22540d6f7 add some bw compat code for old rest_path prototype
sylvain.thenault@logilab.fr
parents: 1840
diff changeset
   485
                kwargs['_restpath'] = self.rest_path()
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   486
        else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   487
            kwargs['rql'] = 'Any X WHERE X eid %s' % self.eid
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   488
        return self._cw.build_url(method, **kwargs)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   489
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   490
    def rest_path(self, use_ext_eid=False): # XXX cw_rest_path
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   491
        """returns a REST-like (relative) path for this entity"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   492
        mainattr, needcheck = self._rest_attr_info()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   493
        etype = str(self.e_schema)
1840
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   494
        path = etype.lower()
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   495
        if mainattr != 'eid':
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   496
            value = getattr(self, mainattr)
2125
19861294506f https://www.logilab.net/cwo/ticket/343724
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2005
diff changeset
   497
            if value is None or unicode(value) == u'':
1840
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   498
                mainattr = 'eid'
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   499
                path += '/eid'
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   500
            elif needcheck:
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   501
                # make sure url is not ambiguous
4363
5c18d82042fb cache result of the COUNT query used to see if a non unique attribute may be used as rest path on the entity instance to avoid recomputing it later
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   502
                try:
5c18d82042fb cache result of the COUNT query used to see if a non unique attribute may be used as rest path on the entity instance to avoid recomputing it later
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   503
                    nbresults = self.__unique
5c18d82042fb cache result of the COUNT query used to see if a non unique attribute may be used as rest path on the entity instance to avoid recomputing it later
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   504
                except AttributeError:
5c18d82042fb cache result of the COUNT query used to see if a non unique attribute may be used as rest path on the entity instance to avoid recomputing it later
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   505
                    rql = 'Any COUNT(X) WHERE X is %s, X %s %%(value)s' % (
5c18d82042fb cache result of the COUNT query used to see if a non unique attribute may be used as rest path on the entity instance to avoid recomputing it later
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   506
                        etype, mainattr)
5c18d82042fb cache result of the COUNT query used to see if a non unique attribute may be used as rest path on the entity instance to avoid recomputing it later
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   507
                    nbresults = self.__unique = self._cw.execute(rql, {'value' : value})[0][0]
1904
e23536d29231 minor refactoring of absolute_url()
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 1842
diff changeset
   508
                if nbresults != 1: # ambiguity?
e23536d29231 minor refactoring of absolute_url()
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 1842
diff changeset
   509
                    mainattr = 'eid'
e23536d29231 minor refactoring of absolute_url()
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 1842
diff changeset
   510
                    path += '/eid'
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   511
        if mainattr == 'eid':
1840
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   512
            if use_ext_eid:
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   513
                value = self.cw_metainformation()['extid']
1840
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   514
            else:
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   515
                value = self.eid
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   516
        return '%s/%s' % (path, self._cw.url_quote(value))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   517
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   518
    def cw_attr_metadata(self, attr, metadata):
1101
0c067de38e46 unification of meta-attributes handling:
sylvain.thenault@logilab.fr
parents: 1098
diff changeset
   519
        """return a metadata for an attribute (None if unspecified)"""
0c067de38e46 unification of meta-attributes handling:
sylvain.thenault@logilab.fr
parents: 1098
diff changeset
   520
        value = getattr(self, '%s_%s' % (attr, metadata), None)
0c067de38e46 unification of meta-attributes handling:
sylvain.thenault@logilab.fr
parents: 1098
diff changeset
   521
        if value is None and metadata == 'encoding':
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   522
            value = self._cw.vreg.property_value('ui.encoding')
1101
0c067de38e46 unification of meta-attributes handling:
sylvain.thenault@logilab.fr
parents: 1098
diff changeset
   523
        return value
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   524
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   525
    def printable_value(self, attr, value=_marker, attrtype=None,
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   526
                        format='text/html', displaytime=True): # XXX cw_printable_value
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   527
        """return a displayable value (i.e. unicode string) which may contains
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   528
        html tags
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   529
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   530
        attr = str(attr)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   531
        if value is _marker:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   532
            value = getattr(self, attr)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   533
        if isinstance(value, basestring):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   534
            value = value.strip()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   535
        if value is None or value == '': # don't use "not", 0 is an acceptable value
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   536
            return u''
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   537
        if attrtype is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   538
            attrtype = self.e_schema.destination(attr)
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   539
        props = self.e_schema.rdef(attr)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   540
        if attrtype == 'String':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   541
            # internalinalized *and* formatted string such as schema
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   542
            # description...
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   543
            if props.internationalizable:
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   544
                value = self._cw._(value)
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   545
            attrformat = self.cw_attr_metadata(attr, 'format')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   546
            if attrformat:
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   547
                return self._cw_mtc_transform(value, attrformat, format,
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   548
                                              self._cw.encoding)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   549
        elif attrtype == 'Bytes':
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   550
            attrformat = self.cw_attr_metadata(attr, 'format')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   551
            if attrformat:
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   552
                encoding = self.cw_attr_metadata(attr, 'encoding')
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   553
                return self._cw_mtc_transform(value.getvalue(), attrformat, format,
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   554
                                              encoding)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   555
            return u''
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   556
        value = printable_value(self._cw, attrtype, value, props,
3212
07d11bacfefe displaytime attribute should not have been removed from there
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3184
diff changeset
   557
                                displaytime=displaytime)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   558
        if format == 'text/html':
2312
af4d8f75c5db use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2125
diff changeset
   559
            value = xml_escape(value)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   560
        return value
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   561
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   562
    def _cw_mtc_transform(self, data, format, target_format, encoding,
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   563
                          _engine=ENGINE):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   564
        trdata = TransformData(data, format, encoding, appobject=self)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   565
        data = _engine.convert(trdata, target_format).decode()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   566
        if format == 'text/html':
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   567
            data = soup2xhtml(data, self._cw.encoding)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   568
        return data
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   569
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   570
    # entity cloning ##########################################################
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   571
5726
c3b99606644d [json] fix json serialization for recent simplejson implementation, and test encoding of entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5573
diff changeset
   572
    def cw_copy(self):
c3b99606644d [json] fix json serialization for recent simplejson implementation, and test encoding of entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5573
diff changeset
   573
        thecopy = copy(self)
c3b99606644d [json] fix json serialization for recent simplejson implementation, and test encoding of entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5573
diff changeset
   574
        thecopy.cw_attr_cache = copy(self.cw_attr_cache)
c3b99606644d [json] fix json serialization for recent simplejson implementation, and test encoding of entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5573
diff changeset
   575
        thecopy._cw_related_cache = {}
c3b99606644d [json] fix json serialization for recent simplejson implementation, and test encoding of entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5573
diff changeset
   576
        return thecopy
c3b99606644d [json] fix json serialization for recent simplejson implementation, and test encoding of entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5573
diff changeset
   577
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   578
    def copy_relations(self, ceid): # XXX cw_copy_relations
3626
017869a514c3 [doc] updated docstrings
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 3552
diff changeset
   579
        """copy relations of the object with the given eid on this
017869a514c3 [doc] updated docstrings
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 3552
diff changeset
   580
        object (this method is called on the newly created copy, and
017869a514c3 [doc] updated docstrings
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 3552
diff changeset
   581
        ceid designates the original entity).
0
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
        By default meta and composite relations are skipped.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   584
        Overrides this if you want another behaviour
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   585
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   586
        assert self.has_eid()
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   587
        execute = self._cw.execute
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   588
        for rschema in self.e_schema.subject_relations():
3689
deb13e88e037 follow yams 0.25 api changes to improve performance
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3683
diff changeset
   589
            if rschema.final or rschema.meta:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   590
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   591
            # skip already defined relations
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   592
            if getattr(self, rschema.type):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   593
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   594
            if rschema.type in self.skip_copy_for:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   595
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   596
            # skip composite relation
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   597
            rdef = self.e_schema.rdef(rschema)
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   598
            if rdef.composite:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   599
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   600
            # skip relation with card in ?1 else we either change the copied
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   601
            # object (inlined relation) or inserting some inconsistency
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   602
            if rdef.cardinality[1] in '?1':
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   603
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   604
            rql = 'SET X %s V WHERE X eid %%(x)s, Y eid %%(y)s, Y %s V' % (
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   605
                rschema.type, rschema.type)
5174
78438ad513ca #759035: Automate addition of eid cachekey in RQL analysis
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   606
            execute(rql, {'x': self.eid, 'y': ceid})
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   607
            self.cw_clear_relation_cache(rschema.type, 'subject')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   608
        for rschema in self.e_schema.object_relations():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   609
            if rschema.meta:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   610
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   611
            # skip already defined relations
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   612
            if self.related(rschema.type, 'object'):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   613
                continue
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   614
            rdef = self.e_schema.rdef(rschema, 'object')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   615
            # skip composite relation
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   616
            if rdef.composite:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   617
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   618
            # skip relation with card in ?1 else we either change the copied
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   619
            # object (inlined relation) or inserting some inconsistency
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   620
            if rdef.cardinality[0] in '?1':
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   621
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   622
            rql = 'SET V %s X WHERE X eid %%(x)s, Y eid %%(y)s, V %s Y' % (
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   623
                rschema.type, rschema.type)
5174
78438ad513ca #759035: Automate addition of eid cachekey in RQL analysis
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   624
            execute(rql, {'x': self.eid, 'y': ceid})
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   625
            self.cw_clear_relation_cache(rschema.type, 'object')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   626
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   627
    # data fetching methods ###################################################
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
    @cached
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   630
    def as_rset(self): # XXX .cw_as_rset
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   631
        """returns a resultset containing `self` information"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   632
        rset = ResultSet([(self.eid,)], 'Any X WHERE X eid %(x)s',
3376
f5c69485381f [appobjects] use __regid__ instead of __id__, more explicit
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3369
diff changeset
   633
                         {'x': self.eid}, [(self.__regid__,)])
4850
bd640b137f50 [refactor] drop rset.vreg attribute, vreg should be accessed through rset.req. Also kill decorate_rset, simply set rset.req where we were calling this method.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4848
diff changeset
   634
        rset.req = self._cw
bd640b137f50 [refactor] drop rset.vreg attribute, vreg should be accessed through rset.req. Also kill decorate_rset, simply set rset.req where we were calling this method.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4848
diff changeset
   635
        return rset
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   636
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   637
    def _cw_to_complete_relations(self):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   638
        """by default complete final relations to when calling .complete()"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   639
        for rschema in self.e_schema.subject_relations():
3689
deb13e88e037 follow yams 0.25 api changes to improve performance
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3683
diff changeset
   640
            if rschema.final:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   641
                continue
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   642
            targets = rschema.objects(self.e_schema)
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   643
            if len(targets) > 1:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   644
                # ambigous relations, the querier doesn't handle
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   645
                # outer join correctly in this case
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   646
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   647
            if rschema.inlined:
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   648
                matching_groups = self._cw.user.matching_groups
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   649
                rdef = rschema.rdef(self.e_schema, targets[0])
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   650
                if matching_groups(rdef.get_groups('read')) and \
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   651
                   all(matching_groups(e.get_groups('read')) for e in targets):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   652
                    yield rschema, 'subject'
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   653
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   654
    def _cw_to_complete_attributes(self, skip_bytes=True, skip_pwd=True):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   655
        for rschema, attrschema in self.e_schema.attribute_definitions():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   656
            # skip binary data by default
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   657
            if skip_bytes and attrschema.type == 'Bytes':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   658
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   659
            attr = rschema.type
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   660
            if attr == 'eid':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   661
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   662
            # password retreival is blocked at the repository server level
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   663
            rdef = rschema.rdef(self.e_schema, attrschema)
3890
d7a270f50f54 backport stable branch (one more time painfully)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3777 3877
diff changeset
   664
            if not self._cw.user.matching_groups(rdef.get_groups('read')) \
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4850
diff changeset
   665
                   or (attrschema.type == 'Password' and skip_pwd):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   666
                self[attr] = None
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   667
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   668
            yield attr
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   669
4408
899b426087ab [entity] small optimization: once an entity has been completed, don't redo it (for nothing)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4406
diff changeset
   670
    _cw_completed = False
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   671
    def complete(self, attributes=None, skip_bytes=True, skip_pwd=True): # XXX cw_complete
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   672
        """complete this entity by adding missing attributes (i.e. query the
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   673
        repository to fill the entity)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   674
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   675
        :type skip_bytes: bool
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   676
        :param skip_bytes:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   677
          if true, attribute of type Bytes won't be considered
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   678
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   679
        assert self.has_eid()
4408
899b426087ab [entity] small optimization: once an entity has been completed, don't redo it (for nothing)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4406
diff changeset
   680
        if self._cw_completed:
899b426087ab [entity] small optimization: once an entity has been completed, don't redo it (for nothing)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4406
diff changeset
   681
            return
899b426087ab [entity] small optimization: once an entity has been completed, don't redo it (for nothing)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4406
diff changeset
   682
        if attributes is None:
899b426087ab [entity] small optimization: once an entity has been completed, don't redo it (for nothing)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4406
diff changeset
   683
            self._cw_completed = True
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   684
        varmaker = rqlvar_maker()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   685
        V = varmaker.next()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   686
        rql = ['WHERE %s eid %%(x)s' % V]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   687
        selected = []
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   688
        for attr in (attributes or self._cw_to_complete_attributes(skip_bytes, skip_pwd)):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   689
            # if attribute already in entity, nothing to do
5726
c3b99606644d [json] fix json serialization for recent simplejson implementation, and test encoding of entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5573
diff changeset
   690
            if self.cw_attr_cache.has_key(attr):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   691
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   692
            # case where attribute must be completed, but is not yet in entity
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   693
            var = varmaker.next()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   694
            rql.append('%s %s %s' % (V, attr, var))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   695
            selected.append((attr, var))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   696
        # +1 since this doen't include the main variable
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   697
        lastattr = len(selected) + 1
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   698
        if attributes is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   699
            # fetch additional relations (restricted to 0..1 relations)
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   700
            for rschema, role in self._cw_to_complete_relations():
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   701
                rtype = rschema.type
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   702
                if self.cw_relation_cached(rtype, role):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   703
                    continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   704
                var = varmaker.next()
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   705
                targettype = rschema.targets(self.e_schema, role)[0]
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   706
                rdef = rschema.role_rdef(self.e_schema, targettype, role)
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   707
                card = rdef.role_cardinality(role)
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   708
                assert card in '1?', '%s %s %s %s' % (self.e_schema, rtype,
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   709
                                                      role, card)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   710
                if role == 'subject':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   711
                    if card == '1':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   712
                        rql.append('%s %s %s' % (V, rtype, var))
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   713
                    else:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   714
                        rql.append('%s %s %s?' % (V, rtype, var))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   715
                else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   716
                    if card == '1':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   717
                        rql.append('%s %s %s' % (var, rtype, V))
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   718
                    else:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   719
                        rql.append('%s? %s %s' % (var, rtype, V))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   720
                selected.append(((rtype, role), var))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   721
        if selected:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   722
            # select V, we need it as the left most selected variable
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   723
            # if some outer join are included to fetch inlined relations
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   724
            rql = 'Any %s,%s %s' % (V, ','.join(var for attr, var in selected),
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   725
                                    ','.join(rql))
5174
78438ad513ca #759035: Automate addition of eid cachekey in RQL analysis
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   726
            rset = self._cw.execute(rql, {'x': self.eid}, build_descr=False)[0]
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   727
            # handle attributes
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   728
            for i in xrange(1, lastattr):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   729
                self[str(selected[i-1][0])] = rset[i]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   730
            # handle relations
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   731
            for i in xrange(lastattr, len(rset)):
2941
196493bd099c [entity] use role instead of x
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2931
diff changeset
   732
                rtype, role = selected[i-1][0]
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   733
                value = rset[i]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   734
                if value is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   735
                    rrset = ResultSet([], rql, {'x': self.eid})
4850
bd640b137f50 [refactor] drop rset.vreg attribute, vreg should be accessed through rset.req. Also kill decorate_rset, simply set rset.req where we were calling this method.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4848
diff changeset
   736
                    rrset.req = self._cw
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   737
                else:
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   738
                    rrset = self._cw.eid_rset(value)
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   739
                self.cw_set_relation_cache(rtype, role, rrset)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   740
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   741
    def cw_attr_value(self, name):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   742
        """get value for the attribute relation <name>, query the repository
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   743
        to get the value if necessary.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   744
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   745
        :type name: str
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   746
        :param name: name of the attribute to get
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
        try:
5726
c3b99606644d [json] fix json serialization for recent simplejson implementation, and test encoding of entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5573
diff changeset
   749
            value = self.cw_attr_cache[name]
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   750
        except KeyError:
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   751
            if not self.cw_is_saved():
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   752
                return None
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   753
            rql = "Any A WHERE X eid %%(x)s, X %s A" % name
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   754
            try:
5174
78438ad513ca #759035: Automate addition of eid cachekey in RQL analysis
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   755
                rset = self._cw.execute(rql, {'x': self.eid})
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   756
            except Unauthorized:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   757
                self[name] = value = None
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   758
            else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   759
                assert rset.rowcount <= 1, (self, rql, rset.rowcount)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   760
                try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   761
                    self[name] = value = rset.rows[0][0]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   762
                except IndexError:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   763
                    # probably a multisource error
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   764
                    self.critical("can't get value for attribute %s of entity with eid %s",
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   765
                                  name, self.eid)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   766
                    if self.e_schema.destination(name) == 'String':
2320
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2312
diff changeset
   767
                        # XXX (syt) imo emtpy string is better
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   768
                        self[name] = value = self._cw._('unaccessible')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   769
                    else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   770
                        self[name] = value = None
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   771
        return value
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   772
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   773
    def related(self, rtype, role='subject', limit=None, entities=False): # XXX .cw_related
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   774
        """returns a resultset of related entities
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   775
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   776
        :param role: is the role played by 'self' in the relation ('subject' or 'object')
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   777
        :param limit: resultset's maximum size
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   778
        :param entities: if True, the entites are returned; if False, a result set is returned
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   779
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   780
        try:
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   781
            return self._cw_relation_cache(rtype, role, entities, limit)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   782
        except KeyError:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   783
            pass
5757
e501806ab489 [entity] when .related() is called on a not-yet-saved entity, return an empty rset/list instead of raising an assertion error
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5733
diff changeset
   784
        if not self.has_eid():
e501806ab489 [entity] when .related() is called on a not-yet-saved entity, return an empty rset/list instead of raising an assertion error
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5733
diff changeset
   785
            if entities:
e501806ab489 [entity] when .related() is called on a not-yet-saved entity, return an empty rset/list instead of raising an assertion error
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5733
diff changeset
   786
                return []
e501806ab489 [entity] when .related() is called on a not-yet-saved entity, return an empty rset/list instead of raising an assertion error
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5733
diff changeset
   787
            return self.empty_rset()
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   788
        rql = self.cw_related_rql(rtype, role)
5174
78438ad513ca #759035: Automate addition of eid cachekey in RQL analysis
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   789
        rset = self._cw.execute(rql, {'x': self.eid})
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   790
        self.cw_set_relation_cache(rtype, role, rset)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   791
        return self.related(rtype, role, limit, entities)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   792
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   793
    def cw_related_rql(self, rtype, role='subject', targettypes=None):
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   794
        rschema = self._cw.vreg.schema[rtype]
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   795
        if role == 'subject':
3672
554a588ffaea [entity] make related_rql honors its targettypes argument
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3671
diff changeset
   796
            restriction = 'E eid %%(x)s, E %s X' % rtype
3130
2486163c4630 allow to specify targettypes in related_rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3047
diff changeset
   797
            if targettypes is None:
2486163c4630 allow to specify targettypes in related_rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3047
diff changeset
   798
                targettypes = rschema.objects(self.e_schema)
3672
554a588ffaea [entity] make related_rql honors its targettypes argument
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3671
diff changeset
   799
            else:
3683
2e4794c97cf4 fix related_rql when target_type specified
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 3680
diff changeset
   800
                restriction += ', X is IN (%s)' % ','.join(targettypes)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   801
            card = greater_card(rschema, (self.e_schema,), targettypes, 0)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   802
        else:
3672
554a588ffaea [entity] make related_rql honors its targettypes argument
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3671
diff changeset
   803
            restriction = 'E eid %%(x)s, X %s E' % rtype
3130
2486163c4630 allow to specify targettypes in related_rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3047
diff changeset
   804
            if targettypes is None:
2486163c4630 allow to specify targettypes in related_rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3047
diff changeset
   805
                targettypes = rschema.subjects(self.e_schema)
3672
554a588ffaea [entity] make related_rql honors its targettypes argument
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3671
diff changeset
   806
            else:
3683
2e4794c97cf4 fix related_rql when target_type specified
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 3680
diff changeset
   807
                restriction += ', X is IN (%s)' % ','.join(targettypes)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   808
            card = greater_card(rschema, targettypes, (self.e_schema,), 1)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   809
        if len(targettypes) > 1:
413
a7366dd3c33c fix bug in entity.related_rql(): fetch_attr list / fetchorder weren't computed correctly
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 397
diff changeset
   810
            fetchattrs_list = []
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   811
            for ttype in targettypes:
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   812
                etypecls = self._cw.vreg['etypes'].etype_class(ttype)
413
a7366dd3c33c fix bug in entity.related_rql(): fetch_attr list / fetchorder weren't computed correctly
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 397
diff changeset
   813
                fetchattrs_list.append(set(etypecls.fetch_attrs))
a7366dd3c33c fix bug in entity.related_rql(): fetch_attr list / fetchorder weren't computed correctly
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 397
diff changeset
   814
            fetchattrs = reduce(set.intersection, fetchattrs_list)
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   815
            rql = etypecls.fetch_rql(self._cw.user, [restriction], fetchattrs,
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   816
                                     settype=False)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   817
        else:
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   818
            etypecls = self._cw.vreg['etypes'].etype_class(targettypes[0])
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   819
            rql = etypecls.fetch_rql(self._cw.user, [restriction], settype=False)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   820
        # optimisation: remove ORDERBY if cardinality is 1 or ? (though
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   821
        # greater_card return 1 for those both cases)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   822
        if card == '1':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   823
            if ' ORDERBY ' in rql:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   824
                rql = '%s WHERE %s' % (rql.split(' ORDERBY ', 1)[0],
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   825
                                       rql.split(' WHERE ', 1)[1])
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   826
        elif not ' ORDERBY ' in rql:
4630
528dee042927 fix #694445: related entity generates weird RQL which in turn generates weird SQL which fails on SQL Server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4460
diff changeset
   827
            args = rql.split(' WHERE ', 1)
528dee042927 fix #694445: related entity generates weird RQL which in turn generates weird SQL which fails on SQL Server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4460
diff changeset
   828
            # if modification_date already retreived, we should use it instead
528dee042927 fix #694445: related entity generates weird RQL which in turn generates weird SQL which fails on SQL Server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4460
diff changeset
   829
            # of adding another variable for sort. This should be be problematic
528dee042927 fix #694445: related entity generates weird RQL which in turn generates weird SQL which fails on SQL Server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4460
diff changeset
   830
            # but it's actually with sqlserver, see ticket #694445
528dee042927 fix #694445: related entity generates weird RQL which in turn generates weird SQL which fails on SQL Server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4460
diff changeset
   831
            if 'X modification_date ' in args[1]:
528dee042927 fix #694445: related entity generates weird RQL which in turn generates weird SQL which fails on SQL Server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4460
diff changeset
   832
                var = args[1].split('X modification_date ', 1)[1].split(',', 1)[0]
528dee042927 fix #694445: related entity generates weird RQL which in turn generates weird SQL which fails on SQL Server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4460
diff changeset
   833
                args.insert(1, var.strip())
528dee042927 fix #694445: related entity generates weird RQL which in turn generates weird SQL which fails on SQL Server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4460
diff changeset
   834
                rql = '%s ORDERBY %s DESC WHERE %s' % tuple(args)
528dee042927 fix #694445: related entity generates weird RQL which in turn generates weird SQL which fails on SQL Server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4460
diff changeset
   835
            else:
528dee042927 fix #694445: related entity generates weird RQL which in turn generates weird SQL which fails on SQL Server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4460
diff changeset
   836
                rql = '%s ORDERBY Z DESC WHERE X modification_date Z, %s' % \
528dee042927 fix #694445: related entity generates weird RQL which in turn generates weird SQL which fails on SQL Server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4460
diff changeset
   837
                      tuple(args)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   838
        return rql
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   839
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   840
    # generic vocabulary methods ##############################################
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   841
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   842
    def cw_unrelated_rql(self, rtype, targettype, role, ordermethod=None,
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   843
                      vocabconstraints=True):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   844
        """build a rql to fetch `targettype` entities unrelated to this entity
3241
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
   845
        using (rtype, role) relation.
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
   846
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
   847
        Consider relation permissions so that returned entities may be actually
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
   848
        linked by `rtype`.
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   849
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   850
        ordermethod = ordermethod or 'fetch_unrelated_order'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   851
        if isinstance(rtype, basestring):
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   852
            rtype = self._cw.vreg.schema.rschema(rtype)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   853
        if role == 'subject':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   854
            evar, searchedvar = 'S', 'O'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   855
            subjtype, objtype = self.e_schema, targettype
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   856
        else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   857
            searchedvar, evar = 'S', 'O'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   858
            objtype, subjtype = self.e_schema, targettype
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   859
        if self.has_eid():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   860
            restriction = ['NOT S %s O' % rtype, '%s eid %%(x)s' % evar]
3241
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
   861
            args = {'x': self.eid}
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
   862
            if role == 'subject':
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
   863
                securitycheck_args = {'fromeid': self.eid}
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
   864
            else:
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
   865
                securitycheck_args = {'toeid': self.eid}
0
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
            restriction = []
3241
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
   868
            args = {}
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
   869
            securitycheck_args = {}
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   870
        rdef = rtype.role_rdef(self.e_schema, targettype, role)
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   871
        insertsecurity = (rdef.has_local_role('add') and not
3890
d7a270f50f54 backport stable branch (one more time painfully)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3777 3877
diff changeset
   872
                          rdef.has_perm(self._cw, 'add', **securitycheck_args))
3961
d1cbf77db999 fix RQLUniqueConstraint behaviour by using a DISTINCT query and allowing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3955
diff changeset
   873
        # XXX consider constraint.mainvars to check if constraint apply
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   874
        if vocabconstraints:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   875
            # RQLConstraint is a subclass for RQLVocabularyConstraint, so they
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   876
            # will be included as well
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   877
            restriction += [cstr.restriction for cstr in rdef.constraints
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   878
                            if isinstance(cstr, RQLVocabularyConstraint)]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   879
        else:
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   880
            restriction += [cstr.restriction for cstr in rdef.constraints
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   881
                            if isinstance(cstr, RQLConstraint)]
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   882
        etypecls = self._cw.vreg['etypes'].etype_class(targettype)
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   883
        rql = etypecls.fetch_rql(self._cw.user, restriction,
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   884
                                 mainvar=searchedvar, ordermethod=ordermethod)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   885
        # ensure we have an order defined
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   886
        if not ' ORDERBY ' in rql:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   887
            before, after = rql.split(' WHERE ', 1)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   888
            rql = '%s ORDERBY %s WHERE %s' % (before, searchedvar, after)
3241
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
   889
        if insertsecurity:
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   890
            rqlexprs = rdef.get_rqlexprs('add')
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   891
            rewriter = RQLRewriter(self._cw)
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   892
            rqlst = self._cw.vreg.parse(self._cw, rql, args)
3826
0c0c051863cb close #511810: bad rql generated when looking for vocabulary for a relation on an entity which doesn't exist (yet)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3746
diff changeset
   893
            if not self.has_eid():
0c0c051863cb close #511810: bad rql generated when looking for vocabulary for a relation on an entity which doesn't exist (yet)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3746
diff changeset
   894
                existant = searchedvar
0c0c051863cb close #511810: bad rql generated when looking for vocabulary for a relation on an entity which doesn't exist (yet)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3746
diff changeset
   895
            else:
0c0c051863cb close #511810: bad rql generated when looking for vocabulary for a relation on an entity which doesn't exist (yet)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3746
diff changeset
   896
                existant = None # instead of 'SO', improve perfs
3241
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
   897
            for select in rqlst.children:
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
   898
                rewriter.rewrite(select, [((searchedvar, searchedvar), rqlexprs)],
3826
0c0c051863cb close #511810: bad rql generated when looking for vocabulary for a relation on an entity which doesn't exist (yet)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3746
diff changeset
   899
                                 select.solutions, args, existant)
3241
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
   900
            rql = rqlst.as_string()
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
   901
        return rql, args
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   902
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   903
    def unrelated(self, rtype, targettype, role='subject', limit=None,
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   904
                  ordermethod=None): # XXX .cw_unrelated
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   905
        """return a result set of target type objects that may be related
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   906
        by a given relation, with self as subject or object
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   907
        """
3241
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
   908
        try:
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   909
            rql, args = self.cw_unrelated_rql(rtype, targettype, role, ordermethod)
3241
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
   910
        except Unauthorized:
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   911
            return self._cw.empty_rset()
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   912
        if limit is not None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   913
            before, after = rql.split(' WHERE ', 1)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   914
            rql = '%s LIMIT %s WHERE %s' % (before, limit, after)
5174
78438ad513ca #759035: Automate addition of eid cachekey in RQL analysis
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   915
        return self._cw.execute(rql, args)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   916
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   917
    # relations cache handling #################################################
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   918
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   919
    def cw_relation_cached(self, rtype, role):
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   920
        """return None if the given relation isn't already cached on the
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   921
        instance, else the content of the cache (a 2-uple (rset, entities)).
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   922
        """
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   923
        return self._cw_related_cache.get('%s_%s' % (rtype, role))
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   924
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   925
    def _cw_relation_cache(self, rtype, role, entities=True, limit=None):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   926
        """return values for the given relation if it's cached on the instance,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   927
        else raise `KeyError`
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   928
        """
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   929
        res = self._cw_related_cache['%s_%s' % (rtype, role)][entities]
3680
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3679
diff changeset
   930
        if limit is not None and limit < len(res):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   931
            if entities:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   932
                res = res[:limit]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   933
            else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   934
                res = res.limit(limit)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   935
        return res
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   936
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   937
    def cw_set_relation_cache(self, rtype, role, rset):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   938
        """set cached values for the given relation"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   939
        if rset:
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   940
            related = list(rset.entities(0))
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   941
            rschema = self._cw.vreg.schema.rschema(rtype)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   942
            if role == 'subject':
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   943
                rcard = rschema.rdef(self.e_schema, related[0].e_schema).cardinality[1]
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   944
                target = 'object'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   945
            else:
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   946
                rcard = rschema.rdef(related[0].e_schema, self.e_schema).cardinality[0]
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   947
                target = 'subject'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   948
            if rcard in '?1':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   949
                for rentity in related:
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   950
                    rentity._cw_related_cache['%s_%s' % (rtype, target)] = (
3552
8facb3324170 [entity] put cached related entities as tuple to be sure no one is modifying
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3546
diff changeset
   951
                        self.as_rset(), (self,))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   952
        else:
3552
8facb3324170 [entity] put cached related entities as tuple to be sure no one is modifying
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3546
diff changeset
   953
            related = ()
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   954
        self._cw_related_cache['%s_%s' % (rtype, role)] = (rset, related)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   955
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   956
    def cw_clear_relation_cache(self, rtype=None, role=None):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   957
        """clear cached values for the given relation or the entire cache if
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   958
        no relation is given
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   959
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   960
        if rtype is None:
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   961
            self._cw_related_cache = {}
5573
8dfb1726526b [entity] clearing adapters cache in clear_relations_cache avoid weird caching issue, notably on repository session's user
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5559
diff changeset
   962
            self._cw_adapters_cache = {}
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   963
        else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   964
            assert role
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   965
            self._cw_related_cache.pop('%s_%s' % (rtype, role), None)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   966
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   967
    def clear_all_caches(self): # XXX cw_clear_all_caches
4408
899b426087ab [entity] small optimization: once an entity has been completed, don't redo it (for nothing)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4406
diff changeset
   968
        """flush all caches on this entity. Further attributes/relations access
899b426087ab [entity] small optimization: once an entity has been completed, don't redo it (for nothing)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4406
diff changeset
   969
        will triggers new database queries to get back values.
899b426087ab [entity] small optimization: once an entity has been completed, don't redo it (for nothing)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4406
diff changeset
   970
899b426087ab [entity] small optimization: once an entity has been completed, don't redo it (for nothing)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4406
diff changeset
   971
        If you use custom caches on your entity class (take care to @cached!),
899b426087ab [entity] small optimization: once an entity has been completed, don't redo it (for nothing)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4406
diff changeset
   972
        you should override this method to clear them as well.
899b426087ab [entity] small optimization: once an entity has been completed, don't redo it (for nothing)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4406
diff changeset
   973
        """
899b426087ab [entity] small optimization: once an entity has been completed, don't redo it (for nothing)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4406
diff changeset
   974
        # clear attributes cache
3665
42f3a66cab51 fix clear_all_cache: ensure we don't remove eid from entity's dict
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3664
diff changeset
   975
        haseid = 'eid' in self
4408
899b426087ab [entity] small optimization: once an entity has been completed, don't redo it (for nothing)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4406
diff changeset
   976
        self._cw_completed = False
5726
c3b99606644d [json] fix json serialization for recent simplejson implementation, and test encoding of entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5573
diff changeset
   977
        self.cw_attr_cache.clear()
4408
899b426087ab [entity] small optimization: once an entity has been completed, don't redo it (for nothing)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4406
diff changeset
   978
        # clear relations cache
5573
8dfb1726526b [entity] clearing adapters cache in clear_relations_cache avoid weird caching issue, notably on repository session's user
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5559
diff changeset
   979
        self.cw_clear_relation_cache()
4460
5c22869079b9 clear rest_path __unique cache in clear_all_caches, fix related test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4451
diff changeset
   980
        # rest path unique cache
5c22869079b9 clear rest_path __unique cache in clear_all_caches, fix related test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4451
diff changeset
   981
        try:
5c22869079b9 clear rest_path __unique cache in clear_all_caches, fix related test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4451
diff changeset
   982
            del self.__unique
5c22869079b9 clear rest_path __unique cache in clear_all_caches, fix related test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4451
diff changeset
   983
        except AttributeError:
5c22869079b9 clear rest_path __unique cache in clear_all_caches, fix related test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4451
diff changeset
   984
            pass
4759
af2e6c377c71 cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4719
diff changeset
   985
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   986
    # raw edition utilities ###################################################
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   987
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   988
    def set_attributes(self, **kwargs): # XXX cw_set_attributes
5115
2e43ef618d14 [repository] forbid usage of set_attributes() in before_add_entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5009
diff changeset
   989
        _check_cw_unsafe(kwargs)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   990
        assert kwargs
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   991
        assert self.cw_is_saved(), "should not call set_attributes while entity "\
5127
3c2dda44e2f6 [entity] explain why the assert failed
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5115
diff changeset
   992
               "hasn't been saved yet"
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   993
        relations = []
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   994
        for key in kwargs:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   995
            relations.append('X %s %%(%s)s' % (key, key))
397
cf577e26f924 don't introduce a spurious 'x' key in the entity-as dict
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 237
diff changeset
   996
        # and now update the database
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   997
        kwargs['x'] = self.eid
4835
13b0b96d7982 [repo] enhanced security handling: deprecates unsafe_execute, in favor of explicit read/write security control using the `enabled_security` context manager. Also code executed on the repository side is now unsafe by default.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4831
diff changeset
   998
        self._cw.execute('SET %s WHERE X eid %%(x)s' % ','.join(relations),
5174
78438ad513ca #759035: Automate addition of eid cachekey in RQL analysis
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   999
                         kwargs)
5115
2e43ef618d14 [repository] forbid usage of set_attributes() in before_add_entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5009
diff changeset
  1000
        kwargs.pop('x')
2e43ef618d14 [repository] forbid usage of set_attributes() in before_add_entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5009
diff changeset
  1001
        # update current local object _after_ the rql query to avoid
2e43ef618d14 [repository] forbid usage of set_attributes() in before_add_entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5009
diff changeset
  1002
        # interferences between the query execution itself and the
2e43ef618d14 [repository] forbid usage of set_attributes() in before_add_entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5009
diff changeset
  1003
        # edited_attributes / skip_security_attributes machinery
2e43ef618d14 [repository] forbid usage of set_attributes() in before_add_entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5009
diff changeset
  1004
        self.update(kwargs)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
  1005
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1006
    def set_relations(self, **kwargs): # XXX cw_set_relations
3955
235a9fda6058 support x.set_relations(a_relation=None) to delete a_relation relations from this entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3919
diff changeset
  1007
        """add relations to the given object. To set a relation where this entity
235a9fda6058 support x.set_relations(a_relation=None) to delete a_relation relations from this entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3919
diff changeset
  1008
        is the object of the relation, use 'reverse_'<relation> as argument name.
235a9fda6058 support x.set_relations(a_relation=None) to delete a_relation relations from this entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3919
diff changeset
  1009
5144
5a09bea07302 [doc/book] a new chapter on how to use the ORM
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 5127
diff changeset
  1010
        Values may be an entity, a list of entities, or None (meaning that all
3955
235a9fda6058 support x.set_relations(a_relation=None) to delete a_relation relations from this entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3919
diff changeset
  1011
        relations of the given type from or to this object should be deleted).
235a9fda6058 support x.set_relations(a_relation=None) to delete a_relation relations from this entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3919
diff changeset
  1012
        """
235a9fda6058 support x.set_relations(a_relation=None) to delete a_relation relations from this entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3919
diff changeset
  1013
        # XXX update cache
4835
13b0b96d7982 [repo] enhanced security handling: deprecates unsafe_execute, in favor of explicit read/write security control using the `enabled_security` context manager. Also code executed on the repository side is now unsafe by default.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4831
diff changeset
  1014
        _check_cw_unsafe(kwargs)
3671
c765adac7f5c new set_relations method on entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3665
diff changeset
  1015
        for attr, values in kwargs.iteritems():
c765adac7f5c new set_relations method on entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3665
diff changeset
  1016
            if attr.startswith('reverse_'):
c765adac7f5c new set_relations method on entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3665
diff changeset
  1017
                restr = 'Y %s X' % attr[len('reverse_'):]
c765adac7f5c new set_relations method on entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3665
diff changeset
  1018
            else:
c765adac7f5c new set_relations method on entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3665
diff changeset
  1019
                restr = 'X %s Y' % attr
3955
235a9fda6058 support x.set_relations(a_relation=None) to delete a_relation relations from this entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3919
diff changeset
  1020
            if values is None:
4991
16f0cec3d008 [entity] fix dumb name error on .set_relations(rel=None)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4990
diff changeset
  1021
                self._cw.execute('DELETE %s WHERE X eid %%(x)s' % restr,
5174
78438ad513ca #759035: Automate addition of eid cachekey in RQL analysis
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
  1022
                                 {'x': self.eid})
3955
235a9fda6058 support x.set_relations(a_relation=None) to delete a_relation relations from this entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3919
diff changeset
  1023
                continue
3746
74192424b2c8 accepts single values as create_entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3689
diff changeset
  1024
            if not isinstance(values, (tuple, list, set, frozenset)):
74192424b2c8 accepts single values as create_entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3689
diff changeset
  1025
                values = (values,)
4835
13b0b96d7982 [repo] enhanced security handling: deprecates unsafe_execute, in favor of explicit read/write security control using the `enabled_security` context manager. Also code executed on the repository side is now unsafe by default.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4831
diff changeset
  1026
            self._cw.execute('SET %s WHERE X eid %%(x)s, Y eid IN (%s)' % (
3671
c765adac7f5c new set_relations method on entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3665
diff changeset
  1027
                restr, ','.join(str(r.eid) for r in values)),
5174
78438ad513ca #759035: Automate addition of eid cachekey in RQL analysis
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
  1028
                             {'x': self.eid})
3671
c765adac7f5c new set_relations method on entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3665
diff changeset
  1029
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1030
    def cw_delete(self, **kwargs):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1031
        assert self.has_eid(), self.eid
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
  1032
        self._cw.execute('DELETE %s X WHERE X eid %%(x)s' % self.e_schema,
4835
13b0b96d7982 [repo] enhanced security handling: deprecates unsafe_execute, in favor of explicit read/write security control using the `enabled_security` context manager. Also code executed on the repository side is now unsafe by default.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4831
diff changeset
  1033
                         {'x': self.eid}, **kwargs)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
  1034
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1035
    # server side utilities ###################################################
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
  1036
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1037
    def _cw_rql_set_value(self, attr, value):
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1038
        """call by rql execution plan when some attribute is modified
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1039
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1040
        don't use dict api in such case since we don't want attribute to be
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1041
        added to skip_security_attributes.
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1042
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1043
        This method is for internal use, you should not use it.
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1044
        """
5726
c3b99606644d [json] fix json serialization for recent simplejson implementation, and test encoding of entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5573
diff changeset
  1045
        self.cw_attr_cache[attr] = value
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1046
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1047
    def _cw_clear_local_perm_cache(self, action):
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1048
        for rqlexpr in self.e_schema.get_rqlexprs(action):
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1049
            self._cw.local_perm_cache.pop((rqlexpr.eid, (('x', self.eid),)), None)
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1050
4970
1f3d8946ea84 fix security issue introduced by 4967:04543ed0bbdc: attributes explicitly set by hooks should not be checked by security hooks
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4965
diff changeset
  1051
    @property
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1052
    def _cw_skip_security_attributes(self):
4970
1f3d8946ea84 fix security issue introduced by 4967:04543ed0bbdc: attributes explicitly set by hooks should not be checked by security hooks
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4965
diff changeset
  1053
        try:
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1054
            return self.__cw_skip_security_attributes
4970
1f3d8946ea84 fix security issue introduced by 4967:04543ed0bbdc: attributes explicitly set by hooks should not be checked by security hooks
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4965
diff changeset
  1055
        except:
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1056
            self.__cw_skip_security_attributes = set()
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1057
            return self.__cw_skip_security_attributes
4970
1f3d8946ea84 fix security issue introduced by 4967:04543ed0bbdc: attributes explicitly set by hooks should not be checked by security hooks
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4965
diff changeset
  1058
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1059
    def _cw_set_defaults(self):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1060
        """set default values according to the schema"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1061
        for attr, value in self.e_schema.defaults():
5726
c3b99606644d [json] fix json serialization for recent simplejson implementation, and test encoding of entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5573
diff changeset
  1062
            if not self.cw_attr_cache.has_key(attr):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1063
                self[str(attr)] = value
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1064
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1065
    def _cw_check(self, creation=False):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1066
        """check this entity against its schema. Only final relation
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1067
        are checked here, constraint on actual relations are checked in hooks
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1068
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1069
        # necessary since eid is handled specifically and yams require it to be
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1070
        # in the dictionary
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
  1071
        if self._cw is None:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1072
            _ = unicode
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1073
        else:
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
  1074
            _ = self._cw._
4988
d85f639e9150 [yams] on creation, specify relations anyway so we don't get spurious warning for accessing eid through the dict api on yams validation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4970
diff changeset
  1075
        if creation:
4965
04543ed0bbdc [source] only consider edited_attributes in source.preprocess_entity()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4913
diff changeset
  1076
            # on creations, we want to check all relations, especially
04543ed0bbdc [source] only consider edited_attributes in source.preprocess_entity()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4913
diff changeset
  1077
            # required attributes
4988
d85f639e9150 [yams] on creation, specify relations anyway so we don't get spurious warning for accessing eid through the dict api on yams validation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4970
diff changeset
  1078
            relations = [rschema for rschema in self.e_schema.subject_relations()
d85f639e9150 [yams] on creation, specify relations anyway so we don't get spurious warning for accessing eid through the dict api on yams validation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4970
diff changeset
  1079
                         if rschema.final and rschema.type != 'eid']
d85f639e9150 [yams] on creation, specify relations anyway so we don't get spurious warning for accessing eid through the dict api on yams validation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4970
diff changeset
  1080
        elif hasattr(self, 'edited_attributes'):
4965
04543ed0bbdc [source] only consider edited_attributes in source.preprocess_entity()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4913
diff changeset
  1081
            relations = [self._cw.vreg.schema.rschema(rtype)
04543ed0bbdc [source] only consider edited_attributes in source.preprocess_entity()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4913
diff changeset
  1082
                         for rtype in self.edited_attributes]
4988
d85f639e9150 [yams] on creation, specify relations anyway so we don't get spurious warning for accessing eid through the dict api on yams validation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4970
diff changeset
  1083
        else:
d85f639e9150 [yams] on creation, specify relations anyway so we don't get spurious warning for accessing eid through the dict api on yams validation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4970
diff changeset
  1084
            relations = None
4965
04543ed0bbdc [source] only consider edited_attributes in source.preprocess_entity()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4913
diff changeset
  1085
        self.e_schema.check(self, creation=creation, _=_,
04543ed0bbdc [source] only consider edited_attributes in source.preprocess_entity()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4913
diff changeset
  1086
                            relations=relations)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1087
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1088
    @deprecated('[3.9] use entity.cw_attr_value(attr)')
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1089
    def get_value(self, name):
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1090
        return self.cw_attr_value(name)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
  1091
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1092
    @deprecated('[3.9] use entity.cw_delete()')
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1093
    def delete(self, **kwargs):
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1094
        return self.cw_delete(**kwargs)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1095
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1096
    @deprecated('[3.9] use entity.cw_attr_metadata(attr, metadata)')
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1097
    def attr_metadata(self, attr, metadata):
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1098
        return self.cw_attr_metadata(attr, metadata)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
  1099
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1100
    @deprecated('[3.9] use entity.cw_has_perm(action)')
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1101
    def has_perm(self, action):
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1102
        return self.cw_has_perm(action)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1103
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1104
    @deprecated('[3.9] use entity.cw_set_relation_cache(rtype, role, rset)')
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1105
    def set_related_cache(self, rtype, role, rset):
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1106
        self.cw_set_relation_cache(rtype, role, rset)
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1107
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1108
    @deprecated('[3.9] use entity.cw_clear_relation_cache(rtype, role, rset)')
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1109
    def clear_related_cache(self, rtype=None, role=None):
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1110
        self.cw_clear_relation_cache(rtype, role)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1111
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1112
# attribute and relation descriptors ##########################################
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1113
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1114
class Attribute(object):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1115
    """descriptor that controls schema attribute access"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1116
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1117
    def __init__(self, attrname):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1118
        assert attrname != 'eid'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1119
        self._attrname = attrname
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1120
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1121
    def __get__(self, eobj, eclass):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1122
        if eobj is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1123
            return self
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1124
        return eobj.cw_attr_value(self._attrname)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1125
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1126
    def __set__(self, eobj, value):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1127
        eobj[self._attrname] = value
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1128
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
  1129
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1130
class Relation(object):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1131
    """descriptor that controls schema relation access"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1132
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
  1133
    def __init__(self, rschema, role):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1134
        self._rtype = rschema.type
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
  1135
        self._role = role
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1136
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1137
    def __get__(self, eobj, eclass):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1138
        if eobj is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1139
            raise AttributeError('%s cannot be only be accessed from instances'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1140
                                 % self._rtype)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1141
        return eobj.related(self._rtype, self._role, entities=True)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
  1142
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1143
    def __set__(self, eobj, value):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1144
        raise NotImplementedError
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1145
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1146
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1147
from logging import getLogger
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1148
from cubicweb import set_log_methods
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1149
set_log_methods(Entity, getLogger('cubicweb.entity'))