entity.py
author Sylvain Thénault <sylvain.thenault@logilab.fr>
Fri, 08 Apr 2011 09:02:55 +0200
branchstable
changeset 7200 81fd6e40a6a8
parent 7139 20807d3d7cf6
child 7206 2723c52a0795
child 7210 29cd85f20ccb
permissions -rw-r--r--
[entity creation] ensure this is a relation and not an attribute before moving things into pending_relations because value is a list Using a list for attributes may be used for later type specific casting (e.g. timeseries)
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
6954
f9a84d54ebf3 [doc] update some copyrights
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6812
diff changeset
     1
# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
5421
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 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
1154
9b23a6836c32 support for old __rtags__
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
    22
from warnings import warn
9b23a6836c32 support for old __rtags__
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
    23
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    24
from logilab.common import interface
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    25
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
    26
from logilab.common.deprecation import deprecated
2312
af4d8f75c5db use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2125
diff changeset
    27
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
    28
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    29
from rql.utils import rqlvar_maker
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    30
3664
af7ca3597b8d use typed_eid
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3626
diff changeset
    31
from cubicweb import Unauthorized, typed_eid
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    32
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
    33
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
    34
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
    35
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
    36
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
    37
from cubicweb.rqlrewrite import RQLRewriter
709
b21ee900c732 avoid dependency to common
sylvain.thenault@logilab.fr
parents: 707
diff changeset
    38
4023
eae23c40627a drop common subpackage
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3998
diff changeset
    39
from cubicweb.uilib import printable_value, soup2xhtml
eae23c40627a drop common subpackage
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3998
diff changeset
    40
from cubicweb.mixins import MI_REL_TRIGGERS
eae23c40627a drop common subpackage
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3998
diff changeset
    41
from cubicweb.mttransforms import ENGINE
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    42
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    43
_marker = object()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    44
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    45
def greater_card(rschema, subjtypes, objtypes, index):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    46
    for subjtype in subjtypes:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    47
        for objtype in objtypes:
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
    48
            card = rschema.rdef(subjtype, objtype).cardinality[index]
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    49
            if card in '+*':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    50
                return card
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    51
    return '1'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    52
6099
b22a4a3895df work around Apache's mod_proxy limitation with special chars in URLs by not using Rest urls when such a case is detected
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6098
diff changeset
    53
def can_use_rest_path(value):
b22a4a3895df work around Apache's mod_proxy limitation with special chars in URLs by not using Rest urls when such a case is detected
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6098
diff changeset
    54
    """return True if value can be used at the end of a Rest URL path"""
b22a4a3895df work around Apache's mod_proxy limitation with special chars in URLs by not using Rest urls when such a case is detected
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6098
diff changeset
    55
    if value is None:
b22a4a3895df work around Apache's mod_proxy limitation with special chars in URLs by not using Rest urls when such a case is detected
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6098
diff changeset
    56
        return False
b22a4a3895df work around Apache's mod_proxy limitation with special chars in URLs by not using Rest urls when such a case is detected
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6098
diff changeset
    57
    value = unicode(value)
b22a4a3895df work around Apache's mod_proxy limitation with special chars in URLs by not using Rest urls when such a case is detected
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6098
diff changeset
    58
    # the check for ?, /, & are to prevent problems when running
b22a4a3895df work around Apache's mod_proxy limitation with special chars in URLs by not using Rest urls when such a case is detected
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6098
diff changeset
    59
    # behind Apache mod_proxy
b22a4a3895df work around Apache's mod_proxy limitation with special chars in URLs by not using Rest urls when such a case is detected
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6098
diff changeset
    60
    if value == u'' or u'?' in value or u'/' in value or u'&' in value:
b22a4a3895df work around Apache's mod_proxy limitation with special chars in URLs by not using Rest urls when such a case is detected
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6098
diff changeset
    61
        return False
b22a4a3895df work around Apache's mod_proxy limitation with special chars in URLs by not using Rest urls when such a case is detected
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6098
diff changeset
    62
    return True
b22a4a3895df work around Apache's mod_proxy limitation with special chars in URLs by not using Rest urls when such a case is detected
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6098
diff changeset
    63
b22a4a3895df work around Apache's mod_proxy limitation with special chars in URLs by not using Rest urls when such a case is detected
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6098
diff changeset
    64
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
    65
class Entity(AppObject):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    66
    """an entity instance has e_schema automagically set on
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    67
    the class and instances has access to their issuing cursor.
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
    68
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    69
    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
    70
    class. Becare that among attributes, 'eid' is *NEITHER* stored in the
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    71
    dict containment (which acts as a cache for other attributes dynamically
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    72
    fetched)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    73
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    74
    :type e_schema: `cubicweb.schema.EntitySchema`
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    75
    :ivar e_schema: the entity's schema
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    76
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    77
    :type rest_var: str
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    78
    :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
    79
                    If None is specified, the first non-meta attribute will
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    80
                    be used
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
    81
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    82
    :type skip_copy_for: list
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    83
    :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
    84
                         this kind of entity. Note that some relations such
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    85
                         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
    86
                         cardinality are always skipped.
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    87
    """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    88
    __registry__ = 'etypes'
717
54b873918b48 kill id_registerer
sylvain.thenault@logilab.fr
parents: 714
diff changeset
    89
    __select__ = yes()
1264
fe2934a7df7f cleanup, avoid spurious warning
sylvain.thenault@logilab.fr
parents: 1177
diff changeset
    90
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
    91
    # class attributes that must be set in class definition
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    92
    rest_attr = None
1138
22f634977c95 make pylint happy, fix some bugs on the way
sylvain.thenault@logilab.fr
parents: 1132
diff changeset
    93
    fetch_attrs = None
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2877
diff changeset
    94
    skip_copy_for = ('in_state',)
1264
fe2934a7df7f cleanup, avoid spurious warning
sylvain.thenault@logilab.fr
parents: 1177
diff changeset
    95
    # class attributes set automatically at registration time
fe2934a7df7f cleanup, avoid spurious warning
sylvain.thenault@logilab.fr
parents: 1177
diff changeset
    96
    e_schema = None
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
    97
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    98
    @classmethod
2807
696ff03f9a58 __initialize__ needs the schema as argument
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2788
diff changeset
    99
    def __initialize__(cls, schema):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   100
        """initialize a specific entity class by adding descriptors to access
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   101
        entity type's attributes and relations
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   102
        """
3376
f5c69485381f [appobjects] use __regid__ instead of __id__, more explicit
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3369
diff changeset
   103
        etype = cls.__regid__
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   104
        assert etype != 'Any', etype
2807
696ff03f9a58 __initialize__ needs the schema as argument
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2788
diff changeset
   105
        cls.e_schema = eschema = schema.eschema(etype)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   106
        for rschema, _ in eschema.attribute_definitions():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   107
            if rschema.type == 'eid':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   108
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   109
            setattr(cls, rschema.type, Attribute(rschema.type))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   110
        mixins = []
2941
196493bd099c [entity] use role instead of x
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2931
diff changeset
   111
        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
   112
            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
   113
                mixin = MI_REL_TRIGGERS[(rschema, role)]
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   114
                if not (issubclass(cls, mixin) or mixin in mixins): # already mixed ?
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   115
                    mixins.append(mixin)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   116
                for iface in getattr(mixin, '__implements__', ()):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   117
                    if not interface.implements(cls, iface):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   118
                        interface.extend(cls, iface)
2941
196493bd099c [entity] use role instead of x
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2931
diff changeset
   119
            if role == 'subject':
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   120
                attr = rschema.type
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   121
            else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   122
                attr = 'reverse_%s' % rschema.type
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   123
            setattr(cls, attr, Relation(rschema, role))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   124
        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
   125
            # 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
   126
            # 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
   127
            # 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
   128
            # 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
   129
            # 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
   130
            #
f91bd15f427c fix nasty pluggable mixins bug, where mixins take precedence other user class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   131
            # 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
   132
            # 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
   133
            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
   134
            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
   135
            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
   136
            cls.info('plugged %s mixins on %s', mixins, cls)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   137
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   138
    fetch_attrs = ('modification_date',)
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   139
    @classmethod
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   140
    def fetch_order(cls, attr, var):
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   141
        """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
   142
        this type are fetched
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   143
        """
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   144
        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
   145
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   146
    @classmethod
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   147
    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
   148
        """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
   149
        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
   150
        new relation on an edited entity).
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   151
        """
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   152
        if attr == 'modification_date':
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   153
            return '%s DESC' % var
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   154
        return None
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   155
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   156
    @classmethod
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   157
    def fetch_rql(cls, user, restriction=None, fetchattrs=None, mainvar='X',
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   158
                  settype=True, ordermethod='fetch_order'):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   159
        """return a rql to fetch all entities of the class type"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   160
        restrictions = restriction or []
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   161
        if settype:
3376
f5c69485381f [appobjects] use __regid__ instead of __id__, more explicit
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3369
diff changeset
   162
            restrictions.append('%s is %s' % (mainvar, cls.__regid__))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   163
        if fetchattrs is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   164
            fetchattrs = cls.fetch_attrs
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   165
        selection = [mainvar]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   166
        orderby = []
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   167
        # start from 26 to avoid possible conflicts with X
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   168
        varmaker = rqlvar_maker(index=26)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   169
        cls._fetch_restrictions(mainvar, varmaker, fetchattrs, selection,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   170
                                orderby, restrictions, user, ordermethod)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   171
        rql = 'Any %s' % ','.join(selection)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   172
        if orderby:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   173
            rql +=  ' ORDERBY %s' % ','.join(orderby)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   174
        rql += ' WHERE %s' % ', '.join(restrictions)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   175
        return rql
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   176
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   177
    @classmethod
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   178
    def _fetch_restrictions(cls, mainvar, varmaker, fetchattrs,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   179
                            selection, orderby, restrictions, user,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   180
                            ordermethod='fetch_order', visited=None):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   181
        eschema = cls.e_schema
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   182
        if visited is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   183
            visited = set((eschema.type,))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   184
        elif eschema.type in visited:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   185
            # avoid infinite recursion
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   186
            return
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   187
        else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   188
            visited.add(eschema.type)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   189
        _fetchattrs = []
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   190
        for attr in fetchattrs:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   191
            try:
3689
deb13e88e037 follow yams 0.25 api changes to improve performance
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3683
diff changeset
   192
                rschema = eschema.subjrels[attr]
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   193
            except KeyError:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   194
                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
   195
                            attr, cls.__regid__)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   196
                continue
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   197
            rdef = eschema.rdef(attr)
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   198
            if not user.matching_groups(rdef.get_groups('read')):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   199
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   200
            var = varmaker.next()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   201
            selection.append(var)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   202
            restriction = '%s %s %s' % (mainvar, attr, var)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   203
            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
   204
            if not rschema.final:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   205
                # XXX this does not handle several destination types
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   206
                desttype = rschema.objects(eschema.type)[0]
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   207
                card = rdef.cardinality[0]
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   208
                if card not in '?1':
2928
edfdb69df6e8 oops, not self but cls here
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2877
diff changeset
   209
                    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
   210
                                 attr, cls)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   211
                    selection.pop()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   212
                    restrictions.pop()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   213
                    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
   214
                # 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
   215
                # (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
   216
                # 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
   217
                # 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
   218
                restrictions[-1] += '?'
4049
5838a4b0766d 3.5 api update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4023
diff changeset
   219
                # 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
   220
                destcls = user._cw.vreg['etypes'].etype_class(desttype)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   221
                destcls._fetch_restrictions(var, varmaker, destcls.fetch_attrs,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   222
                                            selection, orderby, restrictions,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   223
                                            user, ordermethod, visited=visited)
6258
9b5c008267b0 [entity] give ordermethod=None to fetch_rql to tell you don't want a specific order
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
   224
            if ordermethod is not None:
9b5c008267b0 [entity] give ordermethod=None to fetch_rql to tell you don't want a specific order
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
   225
                orderterm = getattr(cls, ordermethod)(attr, var)
9b5c008267b0 [entity] give ordermethod=None to fetch_rql to tell you don't want a specific order
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
   226
                if orderterm:
9b5c008267b0 [entity] give ordermethod=None to fetch_rql to tell you don't want a specific order
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
   227
                    orderby.append(orderterm)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   228
        return selection, orderby, restrictions
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   229
1471
c889c3bcf5ec new parent_classes method (cached)
sylvain.thenault@logilab.fr
parents: 1435
diff changeset
   230
    @classmethod
c889c3bcf5ec new parent_classes method (cached)
sylvain.thenault@logilab.fr
parents: 1435
diff changeset
   231
    @cached
1840
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   232
    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
   233
        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
   234
        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
   235
            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
   236
            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
   237
        else:
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   238
            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
   239
                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
   240
                    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
   241
                    needcheck = False
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   242
                    break
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   243
        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
   244
            needcheck = False
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   245
        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
   246
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
   247
    @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
   248
    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
   249
        """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
   250
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
        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
   252
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
        >>> 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
   254
        >>> 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
   255
        >>> 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
   256
        >>> 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
   257
        ...                          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
   258
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
        """
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
        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
   261
        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
   262
        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
   263
        pending_relations = []
7200
81fd6e40a6a8 [entity creation] ensure this is a relation and not an attribute before moving things into pending_relations because value is a list
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7139
diff changeset
   264
        eschema = cls.e_schema
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
   265
        for attr, value in kwargs.items():
7200
81fd6e40a6a8 [entity creation] ensure this is a relation and not an attribute before moving things into pending_relations because value is a list
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7139
diff changeset
   266
            if attr.startswith('reverse_'):
81fd6e40a6a8 [entity creation] ensure this is a relation and not an attribute before moving things into pending_relations because value is a list
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7139
diff changeset
   267
                attr = attr[len('reverse_'):]
81fd6e40a6a8 [entity creation] ensure this is a relation and not an attribute before moving things into pending_relations because value is a list
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7139
diff changeset
   268
                role = 'object'
81fd6e40a6a8 [entity creation] ensure this is a relation and not an attribute before moving things into pending_relations because value is a list
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7139
diff changeset
   269
            else:
81fd6e40a6a8 [entity creation] ensure this is a relation and not an attribute before moving things into pending_relations because value is a list
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7139
diff changeset
   270
                role = 'subject'
81fd6e40a6a8 [entity creation] ensure this is a relation and not an attribute before moving things into pending_relations because value is a list
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7139
diff changeset
   271
            assert eschema.has_relation(attr, role)
81fd6e40a6a8 [entity creation] ensure this is a relation and not an attribute before moving things into pending_relations because value is a list
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7139
diff changeset
   272
            rschema = eschema.subjrels[attr] if role == 'subject' else eschema.objrels[attr]
81fd6e40a6a8 [entity creation] ensure this is a relation and not an attribute before moving things into pending_relations because value is a list
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7139
diff changeset
   273
            if not rschema.final and isinstance(value, (tuple, list, set, frozenset)):
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
   274
                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
   275
                    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
   276
                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
   277
                    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
   278
                    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
   279
                    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
   280
            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
   281
                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
   282
                # 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
   283
                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
   284
                    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
   285
                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
   286
                    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
   287
                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
   288
                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
   289
                    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
   290
                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
   291
            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
   292
                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
   293
        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
   294
            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
   295
        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
   296
            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
   297
        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
   298
        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
   299
            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
   300
                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
   301
            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
   302
                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
   303
            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
   304
                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
   305
                    {'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
   306
        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
   307
1435
6cd6172718bb allow to instantiate an entity without rset
sylvain.thenault@logilab.fr
parents: 1363
diff changeset
   308
    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
   309
        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
   310
        self._cw_related_cache = {}
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   311
        if rset is not None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   312
            self.eid = rset[row][col]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   313
        else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   314
            self.eid = None
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   315
        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
   316
        self.cw_attr_cache = {}
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   317
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   318
    def __repr__(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   319
        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
   320
            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
   321
6142
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
   322
    def __cmp__(self, other):
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
   323
        raise NotImplementedError('comparison not implemented for %s' % self.__class__)
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
   324
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
   325
    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
   326
        """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
   327
        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
   328
        """
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
   329
        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
   330
        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
   331
        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
   332
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   333
    def cw_adapt_to(self, interface):
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   334
        """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
   335
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   336
        return None if it can not be adapted.
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   337
        """
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   338
        try:
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   339
            cache = self._cw_adapters_cache
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   340
        except AttributeError:
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   341
            self._cw_adapters_cache = cache = {}
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   342
        try:
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   343
            return cache[interface]
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   344
        except KeyError:
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   345
            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
   346
                interface, self._cw, entity=self)
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   347
            cache[interface] = adapter
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   348
            return adapter
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   349
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   350
    def has_eid(self): # XXX cw_has_eid
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   351
        """return True if the entity has an attributed eid (False
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   352
        meaning that the entity has to be created
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   353
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   354
        try:
3664
af7ca3597b8d use typed_eid
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3626
diff changeset
   355
            typed_eid(self.eid)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   356
            return True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   357
        except (ValueError, TypeError):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   358
            return False
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   359
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   360
    def cw_is_saved(self):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   361
        """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
   362
        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
   363
        '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
   364
        has an eid *and* is saved in its source.
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   365
        """
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   366
        return self.has_eid() and self._cw_is_saved
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   367
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   368
    @cached
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   369
    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
   370
        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
   371
        res['source'] = self._cw.source_defs()[res['source']]
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   372
        return res
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   373
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   374
    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
   375
        self.e_schema.check_perm(self._cw, action, eid=self.eid)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   376
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   377
    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
   378
        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
   379
6085
8a059eefac75 [entity] entity.view now support initargs as req.view
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5980
diff changeset
   380
    def view(self, __vid, __registry='views', w=None, initargs=None, **kwargs): # XXX cw_view
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   381
        """shortcut to apply a view on this entity"""
6085
8a059eefac75 [entity] entity.view now support initargs as req.view
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5980
diff changeset
   382
        if initargs is None:
8a059eefac75 [entity] entity.view now support initargs as req.view
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5980
diff changeset
   383
            initargs = kwargs
8a059eefac75 [entity] entity.view now support initargs as req.view
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5980
diff changeset
   384
        else:
8a059eefac75 [entity] entity.view now support initargs as req.view
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5980
diff changeset
   385
            initargs.update(kwargs)
4451
65f4665233e6 misc typos found on my way: NameError / SyntaxError / double __select__, <sigh ...>
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4436
diff changeset
   386
        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
   387
                                                row=self.cw_row, col=self.cw_col,
6085
8a059eefac75 [entity] entity.view now support initargs as req.view
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5980
diff changeset
   388
                                                **initargs)
5522
6be95896d49e [entity] avoid getting w in cw_extra_kwargs when calling .view
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   389
        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
   390
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   391
    def absolute_url(self, *args, **kwargs): # XXX cw_url
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   392
        """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
   393
        # 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
   394
        # 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
   395
        if args:
af33833d7571 absolute_url / build_url refactoring to avoid potential name clash
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2058
diff changeset
   396
            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
   397
            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
   398
        else:
af33833d7571 absolute_url / build_url refactoring to avoid potential name clash
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2058
diff changeset
   399
            method = None
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   400
        # in linksearch mode, we don't want external urls else selecting
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   401
        # the object for use in the relation is tricky
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   402
        # XXX search_state is web specific
6317
0d4dd5f6f05c [entity, url] we should not set base_url in kwargs when actually unset
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6307
diff changeset
   403
        use_ext_id = False
6307
c07763c59fcb [entity] fix typo in absolute_url method, breaking some code w/ control of absolute url of external entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6258
diff changeset
   404
        if 'base_url' not in kwargs and \
6100
3cd1e6a74830 fix bug introduced by 6098:a0fde9334dd0
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6099
diff changeset
   405
               getattr(self._cw, 'search_state', ('normal',))[0] == 'normal':
6317
0d4dd5f6f05c [entity, url] we should not set base_url in kwargs when actually unset
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6307
diff changeset
   406
            baseurl = self.cw_metainformation()['source'].get('base-url')
0d4dd5f6f05c [entity, url] we should not set base_url in kwargs when actually unset
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6307
diff changeset
   407
            if baseurl:
0d4dd5f6f05c [entity, url] we should not set base_url in kwargs when actually unset
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6307
diff changeset
   408
                kwargs['base_url'] = baseurl
0d4dd5f6f05c [entity, url] we should not set base_url in kwargs when actually unset
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6307
diff changeset
   409
                use_ext_id = True
1904
e23536d29231 minor refactoring of absolute_url()
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 1842
diff changeset
   410
        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
   411
            try:
6098
a0fde9334dd0 [entity] base_url argument may be explicitly specified for other purpose (eg http/https site version control)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6085
diff changeset
   412
                kwargs['_restpath'] = self.rest_path(use_ext_id)
1842
c7a22540d6f7 add some bw compat code for old rest_path prototype
sylvain.thenault@logilab.fr
parents: 1840
diff changeset
   413
            except TypeError:
3405
9d31c9cb8103 nicer deprecation warnings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3382
diff changeset
   414
                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
   415
                     '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
   416
                kwargs['_restpath'] = self.rest_path()
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   417
        else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   418
            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
   419
        return self._cw.build_url(method, **kwargs)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   420
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   421
    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
   422
        """returns a REST-like (relative) path for this entity"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   423
        mainattr, needcheck = self._rest_attr_info()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   424
        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
   425
        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
   426
        if mainattr != 'eid':
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   427
            value = getattr(self, mainattr)
6099
b22a4a3895df work around Apache's mod_proxy limitation with special chars in URLs by not using Rest urls when such a case is detected
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6098
diff changeset
   428
            if not can_use_rest_path(value):
1840
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   429
                mainattr = 'eid'
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   430
                path += '/eid'
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   431
            elif needcheck:
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   432
                # 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
   433
                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
   434
                    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
   435
                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
   436
                    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
   437
                        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
   438
                    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
   439
                if nbresults != 1: # ambiguity?
e23536d29231 minor refactoring of absolute_url()
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 1842
diff changeset
   440
                    mainattr = 'eid'
e23536d29231 minor refactoring of absolute_url()
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 1842
diff changeset
   441
                    path += '/eid'
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   442
        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
   443
            if use_ext_eid:
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   444
                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
   445
            else:
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   446
                value = self.eid
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   447
        return '%s/%s' % (path, self._cw.url_quote(value))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   448
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   449
    def cw_attr_metadata(self, attr, metadata):
1101
0c067de38e46 unification of meta-attributes handling:
sylvain.thenault@logilab.fr
parents: 1098
diff changeset
   450
        """return a metadata for an attribute (None if unspecified)"""
0c067de38e46 unification of meta-attributes handling:
sylvain.thenault@logilab.fr
parents: 1098
diff changeset
   451
        value = getattr(self, '%s_%s' % (attr, metadata), None)
0c067de38e46 unification of meta-attributes handling:
sylvain.thenault@logilab.fr
parents: 1098
diff changeset
   452
        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
   453
            value = self._cw.vreg.property_value('ui.encoding')
1101
0c067de38e46 unification of meta-attributes handling:
sylvain.thenault@logilab.fr
parents: 1098
diff changeset
   454
        return value
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   455
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   456
    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
   457
                        format='text/html', displaytime=True): # XXX cw_printable_value
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   458
        """return a displayable value (i.e. unicode string) which may contains
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   459
        html tags
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   460
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   461
        attr = str(attr)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   462
        if value is _marker:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   463
            value = getattr(self, attr)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   464
        if isinstance(value, basestring):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   465
            value = value.strip()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   466
        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
   467
            return u''
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   468
        if attrtype is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   469
            attrtype = self.e_schema.destination(attr)
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   470
        props = self.e_schema.rdef(attr)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   471
        if attrtype == 'String':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   472
            # internalinalized *and* formatted string such as schema
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   473
            # description...
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   474
            if props.internationalizable:
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   475
                value = self._cw._(value)
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   476
            attrformat = self.cw_attr_metadata(attr, 'format')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   477
            if attrformat:
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   478
                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
   479
                                              self._cw.encoding)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   480
        elif attrtype == 'Bytes':
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   481
            attrformat = self.cw_attr_metadata(attr, 'format')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   482
            if attrformat:
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   483
                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
   484
                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
   485
                                              encoding)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   486
            return u''
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   487
        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
   488
                                displaytime=displaytime)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   489
        if format == 'text/html':
2312
af4d8f75c5db use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2125
diff changeset
   490
            value = xml_escape(value)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   491
        return value
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   492
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   493
    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
   494
                          _engine=ENGINE):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   495
        trdata = TransformData(data, format, encoding, appobject=self)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   496
        data = _engine.convert(trdata, target_format).decode()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   497
        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
   498
            data = soup2xhtml(data, self._cw.encoding)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   499
        return data
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   500
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   501
    # entity cloning ##########################################################
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   502
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   503
    def copy_relations(self, ceid): # XXX cw_copy_relations
3626
017869a514c3 [doc] updated docstrings
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 3552
diff changeset
   504
        """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
   505
        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
   506
        ceid designates the original entity).
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   507
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   508
        By default meta and composite relations are skipped.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   509
        Overrides this if you want another behaviour
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   510
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   511
        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
   512
        execute = self._cw.execute
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   513
        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
   514
            if rschema.final or rschema.meta:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   515
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   516
            # skip already defined relations
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   517
            if getattr(self, rschema.type):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   518
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   519
            if rschema.type in self.skip_copy_for:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   520
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   521
            # skip composite relation
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   522
            rdef = self.e_schema.rdef(rschema)
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   523
            if rdef.composite:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   524
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   525
            # skip relation with card in ?1 else we either change the copied
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   526
            # object (inlined relation) or inserting some inconsistency
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   527
            if rdef.cardinality[1] in '?1':
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   528
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   529
            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
   530
                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
   531
            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
   532
            self.cw_clear_relation_cache(rschema.type, 'subject')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   533
        for rschema in self.e_schema.object_relations():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   534
            if rschema.meta:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   535
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   536
            # skip already defined relations
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   537
            if self.related(rschema.type, 'object'):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   538
                continue
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   539
            rdef = self.e_schema.rdef(rschema, 'object')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   540
            # skip composite relation
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   541
            if rdef.composite:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   542
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   543
            # skip relation with card in ?1 else we either change the copied
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   544
            # object (inlined relation) or inserting some inconsistency
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   545
            if rdef.cardinality[0] in '?1':
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   546
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   547
            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
   548
                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
   549
            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
   550
            self.cw_clear_relation_cache(rschema.type, 'object')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   551
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   552
    # data fetching methods ###################################################
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   553
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   554
    @cached
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   555
    def as_rset(self): # XXX .cw_as_rset
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   556
        """returns a resultset containing `self` information"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   557
        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
   558
                         {'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
   559
        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
   560
        return rset
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
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_to_complete_relations(self):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   563
        """by default complete final relations to when calling .complete()"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   564
        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
   565
            if rschema.final:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   566
                continue
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   567
            targets = rschema.objects(self.e_schema)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   568
            if rschema.inlined:
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   569
                matching_groups = self._cw.user.matching_groups
5797
7183f32fad13 [entity] fix .complete so we don't crash on missing mandatory relation. Also simplify code. Closes #1058267
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5762
diff changeset
   570
                if all(matching_groups(e.get_groups('read')) and
7183f32fad13 [entity] fix .complete so we don't crash on missing mandatory relation. Also simplify code. Closes #1058267
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5762
diff changeset
   571
                       rschema.rdef(self.e_schema, e).get_groups('read')
7183f32fad13 [entity] fix .complete so we don't crash on missing mandatory relation. Also simplify code. Closes #1058267
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5762
diff changeset
   572
                       for e in targets):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   573
                    yield rschema, 'subject'
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   574
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   575
    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
   576
        for rschema, attrschema in self.e_schema.attribute_definitions():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   577
            # skip binary data by default
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   578
            if skip_bytes and attrschema.type == 'Bytes':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   579
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   580
            attr = rschema.type
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   581
            if attr == 'eid':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   582
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   583
            # password retreival is blocked at the repository server level
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   584
            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
   585
            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
   586
                   or (attrschema.type == 'Password' and skip_pwd):
6142
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
   587
                self.cw_attr_cache[attr] = None
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   588
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   589
            yield attr
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   590
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
   591
    _cw_completed = False
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   592
    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
   593
        """complete this entity by adding missing attributes (i.e. query the
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   594
        repository to fill the entity)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   595
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   596
        :type skip_bytes: bool
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   597
        :param skip_bytes:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   598
          if true, attribute of type Bytes won't be considered
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   599
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   600
        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
   601
        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
   602
            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
   603
        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
   604
            self._cw_completed = True
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   605
        varmaker = rqlvar_maker()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   606
        V = varmaker.next()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   607
        rql = ['WHERE %s eid %%(x)s' % V]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   608
        selected = []
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   609
        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
   610
            # 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
   611
            if self.cw_attr_cache.has_key(attr):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   612
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   613
            # case where attribute must be completed, but is not yet in entity
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   614
            var = varmaker.next()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   615
            rql.append('%s %s %s' % (V, attr, var))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   616
            selected.append((attr, var))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   617
        # +1 since this doen't include the main variable
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   618
        lastattr = len(selected) + 1
6124
c5900230809b [ms] when entity is coming from an external source, don't add non final relations on complete
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6100
diff changeset
   619
        # don't fetch extra relation if attributes specified or of the entity is
c5900230809b [ms] when entity is coming from an external source, don't add non final relations on complete
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6100
diff changeset
   620
        # coming from an external source (may lead to error)
c5900230809b [ms] when entity is coming from an external source, don't add non final relations on complete
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6100
diff changeset
   621
        if attributes is None and self.cw_metainformation()['source']['uri'] == 'system':
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   622
            # 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
   623
            for rschema, role in self._cw_to_complete_relations():
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   624
                rtype = rschema.type
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   625
                if self.cw_relation_cached(rtype, role):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   626
                    continue
5797
7183f32fad13 [entity] fix .complete so we don't crash on missing mandatory relation. Also simplify code. Closes #1058267
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5762
diff changeset
   627
                # at this point we suppose that:
7183f32fad13 [entity] fix .complete so we don't crash on missing mandatory relation. Also simplify code. Closes #1058267
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5762
diff changeset
   628
                # * this is a inlined relation
7183f32fad13 [entity] fix .complete so we don't crash on missing mandatory relation. Also simplify code. Closes #1058267
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5762
diff changeset
   629
                # * entity (self) is the subject
7183f32fad13 [entity] fix .complete so we don't crash on missing mandatory relation. Also simplify code. Closes #1058267
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5762
diff changeset
   630
                # * user has read perm on the relation and on the target entity
7183f32fad13 [entity] fix .complete so we don't crash on missing mandatory relation. Also simplify code. Closes #1058267
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5762
diff changeset
   631
                assert rschema.inlined
7183f32fad13 [entity] fix .complete so we don't crash on missing mandatory relation. Also simplify code. Closes #1058267
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5762
diff changeset
   632
                assert role == 'subject'
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   633
                var = varmaker.next()
5797
7183f32fad13 [entity] fix .complete so we don't crash on missing mandatory relation. Also simplify code. Closes #1058267
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5762
diff changeset
   634
                # keep outer join anyway, we don't want .complete to crash on
7183f32fad13 [entity] fix .complete so we don't crash on missing mandatory relation. Also simplify code. Closes #1058267
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5762
diff changeset
   635
                # missing mandatory relation (see #1058267)
7183f32fad13 [entity] fix .complete so we don't crash on missing mandatory relation. Also simplify code. Closes #1058267
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5762
diff changeset
   636
                rql.append('%s %s %s?' % (V, rtype, var))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   637
                selected.append(((rtype, role), var))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   638
        if selected:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   639
            # select V, we need it as the left most selected variable
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   640
            # if some outer join are included to fetch inlined relations
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   641
            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
   642
                                    ','.join(rql))
6656
bea4ab297e67 [ms entity] proper error on external entity fetch error
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6499
diff changeset
   643
            try:
bea4ab297e67 [ms entity] proper error on external entity fetch error
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6499
diff changeset
   644
                rset = self._cw.execute(rql, {'x': self.eid}, build_descr=False)[0]
bea4ab297e67 [ms entity] proper error on external entity fetch error
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6499
diff changeset
   645
            except IndexError:
bea4ab297e67 [ms entity] proper error on external entity fetch error
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6499
diff changeset
   646
                raise Exception('unable to fetch attributes for entity with eid %s'
bea4ab297e67 [ms entity] proper error on external entity fetch error
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6499
diff changeset
   647
                                % self.eid)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   648
            # handle attributes
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   649
            for i in xrange(1, lastattr):
6142
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
   650
                self.cw_attr_cache[str(selected[i-1][0])] = rset[i]
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   651
            # handle relations
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   652
            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
   653
                rtype, role = selected[i-1][0]
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   654
                value = rset[i]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   655
                if value is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   656
                    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
   657
                    rrset.req = self._cw
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   658
                else:
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   659
                    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
   660
                self.cw_set_relation_cache(rtype, role, rrset)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   661
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   662
    def cw_attr_value(self, name):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   663
        """get value for the attribute relation <name>, query the repository
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   664
        to get the value if necessary.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   665
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   666
        :type name: str
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   667
        :param name: name of the attribute to get
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   668
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   669
        try:
6142
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
   670
            return self.cw_attr_cache[name]
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   671
        except KeyError:
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   672
            if not self.cw_is_saved():
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   673
                return None
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   674
            rql = "Any A WHERE X eid %%(x)s, X %s A" % name
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   675
            try:
5174
78438ad513ca #759035: Automate addition of eid cachekey in RQL analysis
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   676
                rset = self._cw.execute(rql, {'x': self.eid})
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   677
            except Unauthorized:
6142
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
   678
                self.cw_attr_cache[name] = value = None
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   679
            else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   680
                assert rset.rowcount <= 1, (self, rql, rset.rowcount)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   681
                try:
6142
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
   682
                    self.cw_attr_cache[name] = value = rset.rows[0][0]
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   683
                except IndexError:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   684
                    # probably a multisource error
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   685
                    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
   686
                                  name, self.eid)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   687
                    if self.e_schema.destination(name) == 'String':
6142
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
   688
                        self.cw_attr_cache[name] = value = self._cw._('unaccessible')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   689
                    else:
6142
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
   690
                        self.cw_attr_cache[name] = value = None
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
   691
            return value
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   692
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   693
    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
   694
        """returns a resultset of related entities
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   695
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   696
        :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
   697
        :param limit: resultset's maximum size
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   698
        :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
   699
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   700
        try:
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   701
            return self._cw_relation_cache(rtype, role, entities, limit)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   702
        except KeyError:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   703
            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
   704
        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
   705
            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
   706
                return []
6807
7330d1fa02dd [cleanup] pylint detected error (among a ton of false positives due to the dynamic nature of cubicweb's code...)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6792
diff changeset
   707
            return self._cw.empty_rset()
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   708
        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
   709
        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
   710
        self.cw_set_relation_cache(rtype, role, rset)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   711
        return self.related(rtype, role, limit, entities)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   712
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   713
    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
   714
        rschema = self._cw.vreg.schema[rtype]
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   715
        if role == 'subject':
3672
554a588ffaea [entity] make related_rql honors its targettypes argument
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3671
diff changeset
   716
            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
   717
            if targettypes is None:
2486163c4630 allow to specify targettypes in related_rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3047
diff changeset
   718
                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
   719
            else:
3683
2e4794c97cf4 fix related_rql when target_type specified
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 3680
diff changeset
   720
                restriction += ', X is IN (%s)' % ','.join(targettypes)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   721
            card = greater_card(rschema, (self.e_schema,), targettypes, 0)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   722
        else:
3672
554a588ffaea [entity] make related_rql honors its targettypes argument
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3671
diff changeset
   723
            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
   724
            if targettypes is None:
2486163c4630 allow to specify targettypes in related_rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3047
diff changeset
   725
                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
   726
            else:
3683
2e4794c97cf4 fix related_rql when target_type specified
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 3680
diff changeset
   727
                restriction += ', X is IN (%s)' % ','.join(targettypes)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   728
            card = greater_card(rschema, targettypes, (self.e_schema,), 1)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   729
        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
   730
            fetchattrs_list = []
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   731
            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
   732
                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
   733
                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
   734
            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
   735
            rql = etypecls.fetch_rql(self._cw.user, [restriction], fetchattrs,
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   736
                                     settype=False)
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
            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
   739
            rql = etypecls.fetch_rql(self._cw.user, [restriction], settype=False)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   740
        # optimisation: remove ORDERBY if cardinality is 1 or ? (though
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   741
        # greater_card return 1 for those both cases)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   742
        if card == '1':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   743
            if ' ORDERBY ' in rql:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   744
                rql = '%s WHERE %s' % (rql.split(' ORDERBY ', 1)[0],
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   745
                                       rql.split(' WHERE ', 1)[1])
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   746
        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
   747
            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
   748
            # 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
   749
            # 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
   750
            # 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
   751
            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
   752
                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
   753
                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
   754
                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
   755
            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
   756
                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
   757
                      tuple(args)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   758
        return rql
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   759
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   760
    # generic vocabulary methods ##############################################
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   761
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   762
    def cw_unrelated_rql(self, rtype, targettype, role, ordermethod=None,
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   763
                      vocabconstraints=True):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   764
        """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
   765
        using (rtype, role) relation.
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
   766
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
   767
        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
   768
        linked by `rtype`.
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   769
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   770
        ordermethod = ordermethod or 'fetch_unrelated_order'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   771
        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
   772
            rtype = self._cw.vreg.schema.rschema(rtype)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   773
        if role == 'subject':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   774
            evar, searchedvar = 'S', 'O'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   775
            subjtype, objtype = self.e_schema, targettype
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   776
        else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   777
            searchedvar, evar = 'S', 'O'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   778
            objtype, subjtype = self.e_schema, targettype
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   779
        if self.has_eid():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   780
            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
   781
            args = {'x': self.eid}
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
   782
            if role == 'subject':
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
   783
                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
   784
            else:
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
   785
                securitycheck_args = {'toeid': self.eid}
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   786
        else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   787
            restriction = []
3241
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
   788
            args = {}
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
   789
            securitycheck_args = {}
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   790
        rdef = rtype.role_rdef(self.e_schema, targettype, role)
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   791
        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
   792
                          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
   793
        # XXX consider constraint.mainvars to check if constraint apply
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   794
        if vocabconstraints:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   795
            # RQLConstraint is a subclass for RQLVocabularyConstraint, so they
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   796
            # will be included as well
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   797
            restriction += [cstr.restriction for cstr in rdef.constraints
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   798
                            if isinstance(cstr, RQLVocabularyConstraint)]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   799
        else:
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   800
            restriction += [cstr.restriction for cstr in rdef.constraints
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   801
                            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
   802
        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
   803
        rql = etypecls.fetch_rql(self._cw.user, restriction,
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   804
                                 mainvar=searchedvar, ordermethod=ordermethod)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   805
        # ensure we have an order defined
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   806
        if not ' ORDERBY ' in rql:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   807
            before, after = rql.split(' WHERE ', 1)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   808
            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
   809
        if insertsecurity:
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   810
            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
   811
            rewriter = RQLRewriter(self._cw)
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   812
            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
   813
            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
   814
                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
   815
            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
   816
                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
   817
            for select in rqlst.children:
7139
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6954
diff changeset
   818
                varmap = {}
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6954
diff changeset
   819
                for var in 'SO':
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6954
diff changeset
   820
                    if var in select.defined_vars:
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6954
diff changeset
   821
                        varmap[var] = var
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6954
diff changeset
   822
                rewriter.rewrite(select, [(varmap, 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
   823
                                 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
   824
            rql = rqlst.as_string()
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
   825
        return rql, args
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   826
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   827
    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
   828
                  ordermethod=None): # XXX .cw_unrelated
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   829
        """return a result set of target type objects that may be related
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   830
        by a given relation, with self as subject or object
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   831
        """
3241
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
   832
        try:
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   833
            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
   834
        except Unauthorized:
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   835
            return self._cw.empty_rset()
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   836
        if limit is not None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   837
            before, after = rql.split(' WHERE ', 1)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   838
            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
   839
        return self._cw.execute(rql, args)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   840
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   841
    # relations cache handling #################################################
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   842
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   843
    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
   844
        """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
   845
        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
   846
        """
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   847
        return self._cw_related_cache.get('%s_%s' % (rtype, role))
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   848
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   849
    def _cw_relation_cache(self, rtype, role, entities=True, limit=None):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   850
        """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
   851
        else raise `KeyError`
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   852
        """
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   853
        res = self._cw_related_cache['%s_%s' % (rtype, role)][entities]
3680
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3679
diff changeset
   854
        if limit is not None and limit < len(res):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   855
            if entities:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   856
                res = res[:limit]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   857
            else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   858
                res = res.limit(limit)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   859
        return res
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   860
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   861
    def cw_set_relation_cache(self, rtype, role, rset):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   862
        """set cached values for the given relation"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   863
        if rset:
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   864
            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
   865
            rschema = self._cw.vreg.schema.rschema(rtype)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   866
            if role == 'subject':
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   867
                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
   868
                target = 'object'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   869
            else:
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   870
                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
   871
                target = 'subject'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   872
            if rcard in '?1':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   873
                for rentity in related:
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   874
                    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
   875
                        self.as_rset(), (self,))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   876
        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
   877
            related = ()
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   878
        self._cw_related_cache['%s_%s' % (rtype, role)] = (rset, related)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   879
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   880
    def cw_clear_relation_cache(self, rtype=None, role=None):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   881
        """clear cached values for the given relation or the entire cache if
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   882
        no relation is given
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   883
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   884
        if rtype is None:
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   885
            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
   886
            self._cw_adapters_cache = {}
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   887
        else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   888
            assert role
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   889
            self._cw_related_cache.pop('%s_%s' % (rtype, role), None)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   890
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   891
    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
   892
        """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
   893
        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
   894
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
   895
        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
   896
        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
   897
        """
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
   898
        # clear attributes cache
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
   899
        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
   900
        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
   901
        # 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
   902
        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
   903
        # 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
   904
        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
   905
            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
   906
        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
   907
            pass
4759
af2e6c377c71 cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4719
diff changeset
   908
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   909
    # raw edition utilities ###################################################
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   910
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   911
    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
   912
        _check_cw_unsafe(kwargs)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   913
        assert kwargs
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   914
        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
   915
               "hasn't been saved yet"
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   916
        relations = []
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   917
        for key in kwargs:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   918
            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
   919
        # and now update the database
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   920
        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
   921
        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
   922
                         kwargs)
5115
2e43ef618d14 [repository] forbid usage of set_attributes() in before_add_entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5009
diff changeset
   923
        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
   924
        # update current local object _after_ the rql query to avoid
6142
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
   925
        # interferences between the query execution itself and the cw_edited /
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
   926
        # skip_security machinery
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
   927
        self.cw_attr_cache.update(kwargs)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   928
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   929
    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
   930
        """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
   931
        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
   932
5144
5a09bea07302 [doc/book] a new chapter on how to use the ORM
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 5127
diff changeset
   933
        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
   934
        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
   935
        """
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
   936
        # 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
   937
        _check_cw_unsafe(kwargs)
3671
c765adac7f5c new set_relations method on entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3665
diff changeset
   938
        for attr, values in kwargs.iteritems():
c765adac7f5c new set_relations method on entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3665
diff changeset
   939
            if attr.startswith('reverse_'):
c765adac7f5c new set_relations method on entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3665
diff changeset
   940
                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
   941
            else:
c765adac7f5c new set_relations method on entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3665
diff changeset
   942
                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
   943
            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
   944
                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
   945
                                 {'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
   946
                continue
3746
74192424b2c8 accepts single values as create_entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3689
diff changeset
   947
            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
   948
                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
   949
            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
   950
                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
   951
                             {'x': self.eid})
3671
c765adac7f5c new set_relations method on entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3665
diff changeset
   952
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   953
    def cw_delete(self, **kwargs):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   954
        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
   955
        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
   956
                         {'x': self.eid}, **kwargs)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   957
6142
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
   958
    # server side utilities ####################################################
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   959
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   960
    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
   961
        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
   962
            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
   963
6142
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
   964
    # deprecated stuff #########################################################
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   965
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   966
    @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
   967
    def get_value(self, name):
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   968
        return self.cw_attr_value(name)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   969
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   970
    @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
   971
    def delete(self, **kwargs):
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   972
        return self.cw_delete(**kwargs)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   973
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   974
    @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
   975
    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
   976
        return self.cw_attr_metadata(attr, metadata)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   977
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   978
    @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
   979
    def has_perm(self, action):
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   980
        return self.cw_has_perm(action)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   981
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   982
    @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
   983
    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
   984
        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
   985
6812
a637f961665d typo in deprecation warning
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6807
diff changeset
   986
    @deprecated('[3.9] use entity.cw_clear_relation_cache(rtype, role)')
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   987
    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
   988
        self.cw_clear_relation_cache(rtype, role)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   989
5870
d3ec7c4bb373 restore bw compat on Entity.related_rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5797
diff changeset
   990
    @deprecated('[3.9] use entity.cw_related_rql(rtype, [role, [targettypes]])')
d3ec7c4bb373 restore bw compat on Entity.related_rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5797
diff changeset
   991
    def related_rql(self, rtype, role='subject', targettypes=None):
d3ec7c4bb373 restore bw compat on Entity.related_rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5797
diff changeset
   992
        return self.cw_related_rql(rtype, role, targettypes)
d3ec7c4bb373 restore bw compat on Entity.related_rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5797
diff changeset
   993
6142
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
   994
    @property
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
   995
    @deprecated('[3.10] use entity.cw_edited')
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
   996
    def edited_attributes(self):
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
   997
        return self.cw_edited
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
   998
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
   999
    @property
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1000
    @deprecated('[3.10] use entity.cw_edited.skip_security')
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1001
    def skip_security_attributes(self):
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1002
        return self.cw_edited.skip_security
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1003
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1004
    @property
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1005
    @deprecated('[3.10] use entity.cw_edited.skip_security')
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1006
    def _cw_skip_security_attributes(self):
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1007
        return self.cw_edited.skip_security
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1008
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1009
    @property
6792
8834d9d91b66 [deprecation] fix bad warning on entity.querier_pending_relations
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6656
diff changeset
  1010
    @deprecated('[3.10] use entity.cw_edited.querier_pending_relations')
6142
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1011
    def querier_pending_relations(self):
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1012
        return self.cw_edited.querier_pending_relations
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1013
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1014
    @deprecated('[3.10] use key in entity.cw_attr_cache')
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1015
    def __contains__(self, key):
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1016
        return key in self.cw_attr_cache
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1017
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1018
    @deprecated('[3.10] iter on entity.cw_attr_cache')
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1019
    def __iter__(self):
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1020
        return iter(self.cw_attr_cache)
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1021
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1022
    @deprecated('[3.10] use entity.cw_attr_cache[attr]')
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1023
    def __getitem__(self, key):
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1024
        if key == 'eid':
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1025
            warn('[3.7] entity["eid"] is deprecated, use entity.eid instead',
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1026
                 DeprecationWarning, stacklevel=2)
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1027
            return self.eid
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1028
        return self.cw_attr_cache[key]
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1029
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1030
    @deprecated('[3.10] use entity.cw_attr_cache.get(attr[, default])')
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1031
    def get(self, key, default=None):
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1032
        return self.cw_attr_cache.get(key, default)
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1033
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1034
    @deprecated('[3.10] use entity.cw_attr_cache.clear()')
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1035
    def clear(self):
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1036
        self.cw_attr_cache.clear()
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1037
        # XXX clear cw_edited ?
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1038
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1039
    @deprecated('[3.10] use entity.cw_edited[attr] = value or entity.cw_attr_cache[attr] = value')
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1040
    def __setitem__(self, attr, value):
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1041
        """override __setitem__ to update self.cw_edited.
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1042
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1043
        Typically, a before_[update|add]_hook could do::
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1044
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1045
            entity['generated_attr'] = generated_value
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1046
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1047
        and this way, cw_edited will be updated accordingly. Also, add
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1048
        the attribute to skip_security since we don't want to check security
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1049
        for such attributes set by hooks.
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1050
        """
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1051
        if attr == 'eid':
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1052
            warn('[3.7] entity["eid"] = value is deprecated, use entity.eid = value instead',
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1053
                 DeprecationWarning, stacklevel=2)
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1054
            self.eid = value
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1055
        else:
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1056
            try:
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1057
                self.cw_edited[attr] = value
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1058
            except AttributeError:
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1059
                self.cw_attr_cache[attr] = value
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1060
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1061
    @deprecated('[3.10] use del entity.cw_edited[attr]')
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1062
    def __delitem__(self, attr):
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1063
        """override __delitem__ to update self.cw_edited on cleanup of
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1064
        undesired changes introduced in the entity's dict. For example, see the
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1065
        code snippet below from the `forge` cube:
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1066
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1067
        .. sourcecode:: python
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1068
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1069
            edited = self.entity.cw_edited
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1070
            has_load_left = 'load_left' in edited
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1071
            if 'load' in edited and self.entity.load_left is None:
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1072
                self.entity.load_left = self.entity['load']
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1073
            elif not has_load_left and edited:
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1074
                # cleanup, this may cause undesired changes
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1075
                del self.entity['load_left']
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1076
        """
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1077
        del self.cw_edited[attr]
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1078
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1079
    @deprecated('[3.10] use entity.cw_edited.setdefault(attr, default)')
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1080
    def setdefault(self, attr, default):
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1081
        """override setdefault to update self.cw_edited"""
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1082
        return self.cw_edited.setdefault(attr, default)
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1083
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1084
    @deprecated('[3.10] use entity.cw_edited.pop(attr[, default])')
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1085
    def pop(self, attr, *args):
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1086
        """override pop to update self.cw_edited on cleanup of
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1087
        undesired changes introduced in the entity's dict. See `__delitem__`
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1088
        """
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1089
        return self.cw_edited.pop(attr, *args)
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1090
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1091
    @deprecated('[3.10] use entity.cw_edited.update(values)')
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1092
    def update(self, values):
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1093
        """override update to update self.cw_edited. See `__setitem__`
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1094
        """
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1095
        self.cw_edited.update(values)
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1096
5870
d3ec7c4bb373 restore bw compat on Entity.related_rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5797
diff changeset
  1097
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1098
# attribute and relation descriptors ##########################################
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1099
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1100
class Attribute(object):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1101
    """descriptor that controls schema attribute access"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1102
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1103
    def __init__(self, attrname):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1104
        assert attrname != 'eid'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1105
        self._attrname = attrname
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1106
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1107
    def __get__(self, eobj, eclass):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1108
        if eobj is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1109
            return self
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1110
        return eobj.cw_attr_value(self._attrname)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1111
6499
c4123c741c66 [deprecation] enhanced messages
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6498
diff changeset
  1112
    @deprecated('[3.10] assign to entity.cw_attr_cache[attr] or entity.cw_edited[attr]')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1113
    def __set__(self, eobj, value):
6498
0ad62d6b6f8e [bw compat] fix compat for entity.attr assigment
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6467
diff changeset
  1114
        if hasattr(eobj, 'cw_edited') and not eobj.cw_edited.saved:
0ad62d6b6f8e [bw compat] fix compat for entity.attr assigment
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6467
diff changeset
  1115
            eobj.cw_edited[self._attrname] = value
0ad62d6b6f8e [bw compat] fix compat for entity.attr assigment
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6467
diff changeset
  1116
        else:
0ad62d6b6f8e [bw compat] fix compat for entity.attr assigment
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6467
diff changeset
  1117
            eobj.cw_attr_cache[self._attrname] = value
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1118
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
  1119
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1120
class Relation(object):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1121
    """descriptor that controls schema relation access"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1122
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
  1123
    def __init__(self, rschema, role):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1124
        self._rtype = rschema.type
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
  1125
        self._role = role
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1126
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1127
    def __get__(self, eobj, eclass):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1128
        if eobj is None:
6419
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6317
diff changeset
  1129
            raise AttributeError('%s can only be accessed from instances'
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1130
                                 % self._rtype)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1131
        return eobj.related(self._rtype, self._role, entities=True)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
  1132
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1133
    def __set__(self, eobj, value):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1134
        raise NotImplementedError
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1135
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
from logging import getLogger
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1138
from cubicweb import set_log_methods
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1139
set_log_methods(Entity, getLogger('cubicweb.entity'))