entity.py
author Sylvain Thénault <sylvain.thenault@logilab.fr>
Tue, 30 Jul 2013 10:06:06 +0200
branchstable
changeset 9201 b0f6e8c14e7f
parent 9188 0677e03077fb
child 9256 697a8181ba30
child 9277 c964d8cf6efc
permissions -rw-r--r--
[i18ncube] fix crash due to duplicated messages in generated schema.pot Add a test case and fix regression introduced in e713c47a993d. Relates to #2811282
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
9188
0677e03077fb [rqlrewrite] rewrite doesn't need a solutions argument, always use the Select'ones
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8992
diff changeset
     1
# copyright 2003-2013 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
8661
4d24ac49f90d [entity] add a "repo_side" parameter to `_cw_dont_cache_attribute`
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 8660
diff changeset
    23
from functools import partial
1154
9b23a6836c32 support for old __rtags__
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
    24
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    25
from logilab.common import interface
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    26
from logilab.common.decorators import cached
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
    27
from logilab.common.deprecation import deprecated
8190
2a3c1b787688 [vreg] move base registry implementation to logilab.common. Closes #1916014
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7995
diff changeset
    28
from logilab.common.registry import yes
8930
6a02be304486 remove unused import
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 8907
diff changeset
    29
from logilab.mtconverter import TransformData, 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
    30
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    31
from rql.utils import rqlvar_maker
7794
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
    32
from rql.stmts import Select
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
    33
from rql.nodes import (Not, VariableRef, Constant, make_relation,
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
    34
                       Relation as RqlRelation)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    35
8748
f5027f8d2478 drop typed_eid() in favour of int() (closes #2742462)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 8735
diff changeset
    36
from cubicweb import Unauthorized, neg_role
7827
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
    37
from cubicweb.utils import support_args
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    38
from cubicweb.rset import ResultSet
2656
a93ae0f6c0ad R [base classes] only AppObject remaning, no more AppRsetObject
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
    39
from cubicweb.appobject import AppObject
7973
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
    40
from cubicweb.schema import (RQLVocabularyConstraint, RQLConstraint,
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
    41
                             GeneratedConstraint)
3241
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
    42
from cubicweb.rqlrewrite import RQLRewriter
709
b21ee900c732 avoid dependency to common
sylvain.thenault@logilab.fr
parents: 707
diff changeset
    43
7914
fb757a7d887e [request, ui] printable_value is now a method of request, and may be given dict of formatters to use (closes #1984743)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7907
diff changeset
    44
from cubicweb.uilib import soup2xhtml
4023
eae23c40627a drop common subpackage
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3998
diff changeset
    45
from cubicweb.mixins import MI_REL_TRIGGERS
eae23c40627a drop common subpackage
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3998
diff changeset
    46
from cubicweb.mttransforms import ENGINE
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    47
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    48
_marker = object()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    49
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    50
def greater_card(rschema, subjtypes, objtypes, index):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    51
    for subjtype in subjtypes:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    52
        for objtype in objtypes:
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
    53
            card = rschema.rdef(subjtype, objtype).cardinality[index]
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    54
            if card in '+*':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    55
                return card
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    56
    return '1'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    57
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
    58
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
    59
    """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
    60
    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
    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
    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
    63
    # 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
    64
    # 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
    65
    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
    66
        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
    67
    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
    68
7973
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
    69
def rel_vars(rel):
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
    70
    return ((isinstance(rel.children[0], VariableRef)
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
    71
             and rel.children[0].variable or None),
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
    72
            (isinstance(rel.children[1].children[0], VariableRef)
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
    73
             and rel.children[1].children[0].variable or None)
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
    74
            )
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
    75
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
    76
def rel_matches(rel, rtype, role, varname, operator='='):
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
    77
    if rel.r_type == rtype and rel.children[1].operator == operator:
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
    78
        same_role_var_idx = 0 if role == 'subject' else 1
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
    79
        variables = rel_vars(rel)
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
    80
        if variables[same_role_var_idx].name == varname:
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
    81
            return variables[1 - same_role_var_idx]
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
    82
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
    83
def build_cstr_with_linkto_infos(cstr, args, searchedvar, evar,
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
    84
                                 lt_infos, eidvars):
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
    85
    """restrict vocabulary as much as possible in entity creation,
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
    86
    based on infos provided by __linkto form param.
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
    87
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
    88
    Example based on following schema:
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
    89
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
    90
      class works_in(RelationDefinition):
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
    91
          subject = 'CWUser'
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
    92
          object = 'Lab'
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
    93
          cardinality = '1*'
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
    94
          constraints = [RQLConstraint('S in_group G, O welcomes G')]
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
    95
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
    96
      class welcomes(RelationDefinition):
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
    97
          subject = 'Lab'
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
    98
          object = 'CWGroup'
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
    99
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   100
    If you create a CWUser in the "scientists" CWGroup you can show
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   101
    only the labs that welcome them using :
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   102
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   103
      lt_infos = {('in_group', 'subject'): 321}
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   104
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   105
    You get following restriction : 'O welcomes G, G eid 321'
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   106
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   107
    """
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   108
    st = cstr.snippet_rqlst.copy()
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   109
    # replace relations in ST by eid infos from linkto where possible
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   110
    for (info_rtype, info_role), eids in lt_infos.iteritems():
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   111
        eid = eids[0] # NOTE: we currently assume a pruned lt_info with only 1 eid
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   112
        for rel in st.iget_nodes(RqlRelation):
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   113
            targetvar = rel_matches(rel, info_rtype, info_role, evar.name)
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   114
            if targetvar is not None:
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   115
                if targetvar.name in eidvars:
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   116
                    rel.parent.remove(rel)
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   117
                else:
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   118
                    eidrel = make_relation(
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   119
                        targetvar, 'eid', (targetvar.name, 'Substitute'),
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   120
                        Constant)
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   121
                    rel.parent.replace(rel, eidrel)
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   122
                    args[targetvar.name] = eid
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   123
                    eidvars.add(targetvar.name)
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   124
    # if modified ST still contains evar references we must discard the
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   125
    # constraint, otherwise evar is unknown in the final rql query which can
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   126
    # lead to a SQL table cartesian product and multiple occurences of solutions
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   127
    evarname = evar.name
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   128
    for rel in st.iget_nodes(RqlRelation):
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   129
        for variable in rel_vars(rel):
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   130
            if variable and evarname == variable.name:
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   131
                return
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   132
    # else insert snippets into the global tree
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   133
    return GeneratedConstraint(st, cstr.mainvars - set(evarname))
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   134
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   135
def pruned_lt_info(eschema, lt_infos):
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   136
    pruned = {}
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   137
    for (lt_rtype, lt_role), eids in lt_infos.iteritems():
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   138
        # we can only use lt_infos describing relation with a cardinality
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   139
        # of value 1 towards the linked entity
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   140
        if not len(eids) == 1:
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   141
            continue
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   142
        lt_card = eschema.rdef(lt_rtype, lt_role).cardinality[
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   143
            0 if lt_role == 'subject' else 1]
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   144
        if lt_card not in '?1':
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   145
            continue
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   146
        pruned[(lt_rtype, lt_role)] = eids
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   147
    return pruned
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
   148
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
   149
class Entity(AppObject):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   150
    """an entity instance has e_schema automagically set on
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   151
    the class and instances has access to their issuing cursor.
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   152
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   153
    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
   154
    class. Becare that among attributes, 'eid' is *NEITHER* stored in the
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   155
    dict containment (which acts as a cache for other attributes dynamically
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   156
    fetched)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   157
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   158
    :type e_schema: `cubicweb.schema.EntitySchema`
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   159
    :ivar e_schema: the entity's schema
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   160
7816
a8a424a78c26 [entity doc] fix typo (rest_var instead of rest_attr) and cleanup doc
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7803
diff changeset
   161
    :type rest_attr: str
a8a424a78c26 [entity doc] fix typo (rest_var instead of rest_attr) and cleanup doc
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7803
diff changeset
   162
    :cvar rest_attr: indicates which attribute should be used to build REST urls
a8a424a78c26 [entity doc] fix typo (rest_var instead of rest_attr) and cleanup doc
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7803
diff changeset
   163
       If `None` is specified (the default), the first unique attribute will
a8a424a78c26 [entity doc] fix typo (rest_var instead of rest_attr) and cleanup doc
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7803
diff changeset
   164
       be used ('eid' if none found)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   165
7702
73cadb5d0097 [entities] skip_copy_for should be considered for object relations too (closes #1857474)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7552
diff changeset
   166
    :type cw_skip_copy_for: list
73cadb5d0097 [entities] skip_copy_for should be considered for object relations too (closes #1857474)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7552
diff changeset
   167
    :cvar cw_skip_copy_for: a list of couples (rtype, role) for each relation
7816
a8a424a78c26 [entity doc] fix typo (rest_var instead of rest_attr) and cleanup doc
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7803
diff changeset
   168
       that should be skipped when copying this kind of entity. Note that some
a8a424a78c26 [entity doc] fix typo (rest_var instead of rest_attr) and cleanup doc
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7803
diff changeset
   169
       relations such as composite relations or relations that have '?1' as
a8a424a78c26 [entity doc] fix typo (rest_var instead of rest_attr) and cleanup doc
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7803
diff changeset
   170
       object cardinality are always skipped.
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   171
    """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   172
    __registry__ = 'etypes'
717
54b873918b48 kill id_registerer
sylvain.thenault@logilab.fr
parents: 714
diff changeset
   173
    __select__ = yes()
1264
fe2934a7df7f cleanup, avoid spurious warning
sylvain.thenault@logilab.fr
parents: 1177
diff changeset
   174
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   175
    # class attributes that must be set in class definition
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   176
    rest_attr = None
1138
22f634977c95 make pylint happy, fix some bugs on the way
sylvain.thenault@logilab.fr
parents: 1132
diff changeset
   177
    fetch_attrs = None
7702
73cadb5d0097 [entities] skip_copy_for should be considered for object relations too (closes #1857474)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7552
diff changeset
   178
    skip_copy_for = () # bw compat (< 3.14), use cw_skip_copy_for instead
73cadb5d0097 [entities] skip_copy_for should be considered for object relations too (closes #1857474)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7552
diff changeset
   179
    cw_skip_copy_for = [('in_state', 'subject')]
1264
fe2934a7df7f cleanup, avoid spurious warning
sylvain.thenault@logilab.fr
parents: 1177
diff changeset
   180
    # class attributes set automatically at registration time
fe2934a7df7f cleanup, avoid spurious warning
sylvain.thenault@logilab.fr
parents: 1177
diff changeset
   181
    e_schema = None
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   182
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   183
    @classmethod
2807
696ff03f9a58 __initialize__ needs the schema as argument
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2788
diff changeset
   184
    def __initialize__(cls, schema):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   185
        """initialize a specific entity class by adding descriptors to access
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   186
        entity type's attributes and relations
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   187
        """
3376
f5c69485381f [appobjects] use __regid__ instead of __id__, more explicit
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3369
diff changeset
   188
        etype = cls.__regid__
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   189
        assert etype != 'Any', etype
2807
696ff03f9a58 __initialize__ needs the schema as argument
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2788
diff changeset
   190
        cls.e_schema = eschema = schema.eschema(etype)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   191
        for rschema, _ in eschema.attribute_definitions():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   192
            if rschema.type == 'eid':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   193
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   194
            setattr(cls, rschema.type, Attribute(rschema.type))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   195
        mixins = []
2941
196493bd099c [entity] use role instead of x
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2931
diff changeset
   196
        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
   197
            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
   198
                mixin = MI_REL_TRIGGERS[(rschema, role)]
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   199
                if not (issubclass(cls, mixin) or mixin in mixins): # already mixed ?
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   200
                    mixins.append(mixin)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   201
                for iface in getattr(mixin, '__implements__', ()):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   202
                    if not interface.implements(cls, iface):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   203
                        interface.extend(cls, iface)
2941
196493bd099c [entity] use role instead of x
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2931
diff changeset
   204
            if role == 'subject':
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   205
                attr = rschema.type
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   206
            else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   207
                attr = 'reverse_%s' % rschema.type
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   208
            setattr(cls, attr, Relation(rschema, role))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   209
        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
   210
            # 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
   211
            # 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
   212
            # 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
   213
            # 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
   214
            # 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
   215
            #
f91bd15f427c fix nasty pluggable mixins bug, where mixins take precedence other user class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   216
            # 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
   217
            # 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
   218
            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
   219
            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
   220
            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
   221
            cls.info('plugged %s mixins on %s', mixins, cls)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   222
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   223
    fetch_attrs = ('modification_date',)
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   224
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   225
    @classmethod
7827
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   226
    def cw_fetch_order(cls, select, attr, var):
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   227
        """This class method may be used to control sort order when multiple
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   228
        entities of this type are fetched through ORM methods. Its arguments
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   229
        are:
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   230
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   231
        * `select`, the RQL syntax tree
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   232
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   233
        * `attr`, the attribute being watched
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   234
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   235
        * `var`, the variable through which this attribute's value may be
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   236
          accessed in the query
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   237
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   238
        When you want to do some sorting on the given attribute, you should
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   239
        modify the syntax tree accordingly. For instance:
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   240
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   241
        .. sourcecode:: python
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   242
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   243
          from rql import nodes
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   244
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   245
          class Version(AnyEntity):
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   246
              __regid__ = 'Version'
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   247
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   248
              fetch_attrs = ('num', 'description', 'in_state')
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   249
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   250
              @classmethod
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   251
              def cw_fetch_order(cls, select, attr, var):
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   252
                  if attr == 'num':
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   253
                      func = nodes.Function('version_sort_value')
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   254
                      func.append(nodes.variable_ref(var))
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   255
                      sterm = nodes.SortTerm(func, asc=False)
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   256
                      select.add_sort_term(sterm)
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   257
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   258
        The default implementation call
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   259
        :meth:`~cubicweb.entity.Entity.cw_fetch_unrelated_order`
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   260
        """
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   261
        cls.cw_fetch_unrelated_order(select, attr, var)
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   262
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   263
    @classmethod
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   264
    def cw_fetch_unrelated_order(cls, select, attr, var):
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   265
        """This class method may be used to control sort order when multiple entities of
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   266
        this type are fetched to use in edition (e.g. propose them to create a
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   267
        new relation on an edited entity).
7827
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   268
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   269
        See :meth:`~cubicweb.entity.Entity.cw_fetch_unrelated_order` for a
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   270
        description of its arguments and usage.
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   271
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   272
        By default entities will be listed on their modification date descending,
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   273
        i.e. you'll get entities recently modified first.
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   274
        """
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   275
        if attr == 'modification_date':
7827
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   276
            select.add_sort_var(var, asc=False)
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   277
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   278
    @classmethod
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   279
    def fetch_rql(cls, user, restriction=None, fetchattrs=None, mainvar='X',
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   280
                  settype=True, ordermethod='fetch_order'):
7794
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
   281
        st = cls.fetch_rqlst(user, mainvar=mainvar, fetchattrs=fetchattrs,
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
   282
                             settype=settype, ordermethod=ordermethod)
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
   283
        rql = st.as_string()
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
   284
        if restriction:
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
   285
            # cannot use RQLRewriter API to insert 'X rtype %(x)s' restriction
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
   286
            warn('[3.14] fetch_rql: use of `restriction` parameter is '
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
   287
                 'deprecated, please use fetch_rqlst and supply a syntax'
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
   288
                 'tree with your restriction instead', DeprecationWarning)
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
   289
            insert = ' WHERE ' + ','.join(restriction)
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
   290
            if ' WHERE ' in rql:
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
   291
                select, where = rql.split(' WHERE ', 1)
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
   292
                rql = select + insert + ',' + where
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
   293
            else:
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
   294
                rql += insert
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   295
        return rql
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   296
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   297
    @classmethod
7794
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
   298
    def fetch_rqlst(cls, user, select=None, mainvar='X', fetchattrs=None,
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
   299
                    settype=True, ordermethod='fetch_order'):
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
   300
        if select is None:
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
   301
            select = Select()
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
   302
            mainvar = select.get_variable(mainvar)
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
   303
            select.add_selected(mainvar)
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
   304
        elif isinstance(mainvar, basestring):
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
   305
            assert mainvar in select.defined_vars
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
   306
            mainvar = select.get_variable(mainvar)
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
   307
        # eases string -> syntax tree test transition: please remove once stable
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
   308
        select._varmaker = rqlvar_maker(defined=select.defined_vars,
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
   309
                                        aliases=select.aliases, index=26)
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
   310
        if settype:
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
   311
            select.add_type_restriction(mainvar, cls.__regid__)
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
   312
        if fetchattrs is None:
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
   313
            fetchattrs = cls.fetch_attrs
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
   314
        cls._fetch_restrictions(mainvar, select, fetchattrs, user, ordermethod)
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
   315
        return select
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
   316
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
   317
    @classmethod
7798
8930f7a284dd [entity fetchattrs] also fetch ambiguous rtypes even if we do not recurse on them (closes #1720823)
Florent Cayré <florent.cayre@gmail.com>
parents: 7794
diff changeset
   318
    def _fetch_ambiguous_rtypes(cls, select, var, fetchattrs, subjtypes, schema):
8930f7a284dd [entity fetchattrs] also fetch ambiguous rtypes even if we do not recurse on them (closes #1720823)
Florent Cayré <florent.cayre@gmail.com>
parents: 7794
diff changeset
   319
        """find rtypes in `fetchattrs` that relate different subject etypes
8930f7a284dd [entity fetchattrs] also fetch ambiguous rtypes even if we do not recurse on them (closes #1720823)
Florent Cayré <florent.cayre@gmail.com>
parents: 7794
diff changeset
   320
        taken from (`subjtypes`) to different target etypes; these so called
8930f7a284dd [entity fetchattrs] also fetch ambiguous rtypes even if we do not recurse on them (closes #1720823)
Florent Cayré <florent.cayre@gmail.com>
parents: 7794
diff changeset
   321
        "ambiguous" relations, are added directly to the `select` syntax tree
8930f7a284dd [entity fetchattrs] also fetch ambiguous rtypes even if we do not recurse on them (closes #1720823)
Florent Cayré <florent.cayre@gmail.com>
parents: 7794
diff changeset
   322
        selection but removed from `fetchattrs` to avoid the fetch recursion
8930f7a284dd [entity fetchattrs] also fetch ambiguous rtypes even if we do not recurse on them (closes #1720823)
Florent Cayré <florent.cayre@gmail.com>
parents: 7794
diff changeset
   323
        because we have to choose only one targettype for the recursion and
8930f7a284dd [entity fetchattrs] also fetch ambiguous rtypes even if we do not recurse on them (closes #1720823)
Florent Cayré <florent.cayre@gmail.com>
parents: 7794
diff changeset
   324
        adding its own fetch attrs to the selection -when we recurse- would
8930f7a284dd [entity fetchattrs] also fetch ambiguous rtypes even if we do not recurse on them (closes #1720823)
Florent Cayré <florent.cayre@gmail.com>
parents: 7794
diff changeset
   325
        filter out the other possible target types from the result set
8930f7a284dd [entity fetchattrs] also fetch ambiguous rtypes even if we do not recurse on them (closes #1720823)
Florent Cayré <florent.cayre@gmail.com>
parents: 7794
diff changeset
   326
        """
8930f7a284dd [entity fetchattrs] also fetch ambiguous rtypes even if we do not recurse on them (closes #1720823)
Florent Cayré <florent.cayre@gmail.com>
parents: 7794
diff changeset
   327
        for attr in fetchattrs.copy():
8930f7a284dd [entity fetchattrs] also fetch ambiguous rtypes even if we do not recurse on them (closes #1720823)
Florent Cayré <florent.cayre@gmail.com>
parents: 7794
diff changeset
   328
            rschema = schema.rschema(attr)
8930f7a284dd [entity fetchattrs] also fetch ambiguous rtypes even if we do not recurse on them (closes #1720823)
Florent Cayré <florent.cayre@gmail.com>
parents: 7794
diff changeset
   329
            if rschema.final:
8930f7a284dd [entity fetchattrs] also fetch ambiguous rtypes even if we do not recurse on them (closes #1720823)
Florent Cayré <florent.cayre@gmail.com>
parents: 7794
diff changeset
   330
                continue
8930f7a284dd [entity fetchattrs] also fetch ambiguous rtypes even if we do not recurse on them (closes #1720823)
Florent Cayré <florent.cayre@gmail.com>
parents: 7794
diff changeset
   331
            ttypes = None
8930f7a284dd [entity fetchattrs] also fetch ambiguous rtypes even if we do not recurse on them (closes #1720823)
Florent Cayré <florent.cayre@gmail.com>
parents: 7794
diff changeset
   332
            for subjtype in subjtypes:
8930f7a284dd [entity fetchattrs] also fetch ambiguous rtypes even if we do not recurse on them (closes #1720823)
Florent Cayré <florent.cayre@gmail.com>
parents: 7794
diff changeset
   333
                cur_ttypes = set(rschema.objects(subjtype))
8930f7a284dd [entity fetchattrs] also fetch ambiguous rtypes even if we do not recurse on them (closes #1720823)
Florent Cayré <florent.cayre@gmail.com>
parents: 7794
diff changeset
   334
                if ttypes is None:
8930f7a284dd [entity fetchattrs] also fetch ambiguous rtypes even if we do not recurse on them (closes #1720823)
Florent Cayré <florent.cayre@gmail.com>
parents: 7794
diff changeset
   335
                    ttypes = cur_ttypes
8930f7a284dd [entity fetchattrs] also fetch ambiguous rtypes even if we do not recurse on them (closes #1720823)
Florent Cayré <florent.cayre@gmail.com>
parents: 7794
diff changeset
   336
                elif cur_ttypes != ttypes:
8930f7a284dd [entity fetchattrs] also fetch ambiguous rtypes even if we do not recurse on them (closes #1720823)
Florent Cayré <florent.cayre@gmail.com>
parents: 7794
diff changeset
   337
                    # we found an ambiguous relation: remove it from fetchattrs
8930f7a284dd [entity fetchattrs] also fetch ambiguous rtypes even if we do not recurse on them (closes #1720823)
Florent Cayré <florent.cayre@gmail.com>
parents: 7794
diff changeset
   338
                    fetchattrs.remove(attr)
8930f7a284dd [entity fetchattrs] also fetch ambiguous rtypes even if we do not recurse on them (closes #1720823)
Florent Cayré <florent.cayre@gmail.com>
parents: 7794
diff changeset
   339
                    # ... and add it to the selection
8930f7a284dd [entity fetchattrs] also fetch ambiguous rtypes even if we do not recurse on them (closes #1720823)
Florent Cayré <florent.cayre@gmail.com>
parents: 7794
diff changeset
   340
                    targetvar = select.make_variable()
8930f7a284dd [entity fetchattrs] also fetch ambiguous rtypes even if we do not recurse on them (closes #1720823)
Florent Cayré <florent.cayre@gmail.com>
parents: 7794
diff changeset
   341
                    select.add_selected(targetvar)
8930f7a284dd [entity fetchattrs] also fetch ambiguous rtypes even if we do not recurse on them (closes #1720823)
Florent Cayré <florent.cayre@gmail.com>
parents: 7794
diff changeset
   342
                    rel = make_relation(var, attr, (targetvar,), VariableRef)
8930f7a284dd [entity fetchattrs] also fetch ambiguous rtypes even if we do not recurse on them (closes #1720823)
Florent Cayré <florent.cayre@gmail.com>
parents: 7794
diff changeset
   343
                    select.add_restriction(rel)
8930f7a284dd [entity fetchattrs] also fetch ambiguous rtypes even if we do not recurse on them (closes #1720823)
Florent Cayré <florent.cayre@gmail.com>
parents: 7794
diff changeset
   344
                    break
8930f7a284dd [entity fetchattrs] also fetch ambiguous rtypes even if we do not recurse on them (closes #1720823)
Florent Cayré <florent.cayre@gmail.com>
parents: 7794
diff changeset
   345
8930f7a284dd [entity fetchattrs] also fetch ambiguous rtypes even if we do not recurse on them (closes #1720823)
Florent Cayré <florent.cayre@gmail.com>
parents: 7794
diff changeset
   346
    @classmethod
7794
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
   347
    def _fetch_restrictions(cls, mainvar, select, fetchattrs,
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
   348
                            user, ordermethod='fetch_order', visited=None):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   349
        eschema = cls.e_schema
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   350
        if visited is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   351
            visited = set((eschema.type,))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   352
        elif eschema.type in visited:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   353
            # avoid infinite recursion
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   354
            return
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   355
        else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   356
            visited.add(eschema.type)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   357
        _fetchattrs = []
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   358
        for attr in fetchattrs:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   359
            try:
3689
deb13e88e037 follow yams 0.25 api changes to improve performance
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3683
diff changeset
   360
                rschema = eschema.subjrels[attr]
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   361
            except KeyError:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   362
                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
   363
                            attr, cls.__regid__)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   364
                continue
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   365
            rdef = eschema.rdef(attr)
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   366
            if not user.matching_groups(rdef.get_groups('read')):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   367
                continue
7794
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
   368
            if rschema.final or rdef.cardinality[0] in '?1':
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
   369
                var = select.make_variable()
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
   370
                select.add_selected(var)
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
   371
                rel = make_relation(mainvar, attr, (var,), VariableRef)
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
   372
                select.add_restriction(rel)
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
   373
            else:
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
   374
                cls.warning('bad relation %s specified in fetch attrs for %s',
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
   375
                            attr, cls)
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
   376
                continue
3689
deb13e88e037 follow yams 0.25 api changes to improve performance
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3683
diff changeset
   377
            if not rschema.final:
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
   378
                # 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
   379
                # (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
   380
                # 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
   381
                # later information here, systematically add it.
7794
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
   382
                rel.change_optional('right')
7302
c281afe35b8b [entity] fix entity fetch_rql when fetch_attrs contains a rtype with multiple destination etypes which do not have the same fetched attributes themselves (closes #1631282)
Florent Cayré <florent.cayre@gmail.com>
parents: 7288
diff changeset
   383
                targettypes = rschema.objects(eschema.type)
7798
8930f7a284dd [entity fetchattrs] also fetch ambiguous rtypes even if we do not recurse on them (closes #1720823)
Florent Cayré <florent.cayre@gmail.com>
parents: 7794
diff changeset
   384
                vreg = user._cw.vreg # XXX user._cw.vreg iiiirk
8930f7a284dd [entity fetchattrs] also fetch ambiguous rtypes even if we do not recurse on them (closes #1720823)
Florent Cayré <florent.cayre@gmail.com>
parents: 7794
diff changeset
   385
                etypecls = vreg['etypes'].etype_class(targettypes[0])
7302
c281afe35b8b [entity] fix entity fetch_rql when fetch_attrs contains a rtype with multiple destination etypes which do not have the same fetched attributes themselves (closes #1631282)
Florent Cayré <florent.cayre@gmail.com>
parents: 7288
diff changeset
   386
                if len(targettypes) > 1:
c281afe35b8b [entity] fix entity fetch_rql when fetch_attrs contains a rtype with multiple destination etypes which do not have the same fetched attributes themselves (closes #1631282)
Florent Cayré <florent.cayre@gmail.com>
parents: 7288
diff changeset
   387
                    # find fetch_attrs common to all destination types
7798
8930f7a284dd [entity fetchattrs] also fetch ambiguous rtypes even if we do not recurse on them (closes #1720823)
Florent Cayré <florent.cayre@gmail.com>
parents: 7794
diff changeset
   388
                    fetchattrs = vreg['etypes'].fetch_attrs(targettypes)
7803
02e141e41da2 some minor cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7798
diff changeset
   389
                    # ... and handle ambiguous relations
7798
8930f7a284dd [entity fetchattrs] also fetch ambiguous rtypes even if we do not recurse on them (closes #1720823)
Florent Cayré <florent.cayre@gmail.com>
parents: 7794
diff changeset
   390
                    cls._fetch_ambiguous_rtypes(select, var, fetchattrs,
8930f7a284dd [entity fetchattrs] also fetch ambiguous rtypes even if we do not recurse on them (closes #1720823)
Florent Cayré <florent.cayre@gmail.com>
parents: 7794
diff changeset
   391
                                                targettypes, vreg.schema)
7302
c281afe35b8b [entity] fix entity fetch_rql when fetch_attrs contains a rtype with multiple destination etypes which do not have the same fetched attributes themselves (closes #1631282)
Florent Cayré <florent.cayre@gmail.com>
parents: 7288
diff changeset
   392
                else:
c281afe35b8b [entity] fix entity fetch_rql when fetch_attrs contains a rtype with multiple destination etypes which do not have the same fetched attributes themselves (closes #1631282)
Florent Cayré <florent.cayre@gmail.com>
parents: 7288
diff changeset
   393
                    fetchattrs = etypecls.fetch_attrs
7794
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
   394
                etypecls._fetch_restrictions(var, select, fetchattrs,
7302
c281afe35b8b [entity] fix entity fetch_rql when fetch_attrs contains a rtype with multiple destination etypes which do not have the same fetched attributes themselves (closes #1631282)
Florent Cayré <florent.cayre@gmail.com>
parents: 7288
diff changeset
   395
                                             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
   396
            if ordermethod is not None:
7827
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   397
                try:
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   398
                    cmeth = getattr(cls, ordermethod)
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   399
                    warn('[3.14] %s %s class method should be renamed to cw_%s'
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   400
                         % (cls.__regid__, ordermethod, ordermethod),
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   401
                         DeprecationWarning)
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   402
                except AttributeError:
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   403
                    cmeth = getattr(cls, 'cw_' + ordermethod)
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   404
                if support_args(cmeth, 'select'):
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   405
                    cmeth(select, attr, var)
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   406
                else:
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   407
                    warn('[3.14] %s should now take (select, attr, var) and '
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   408
                         'modify the syntax tree when desired instead of '
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   409
                         'returning something' % cmeth, DeprecationWarning)
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   410
                    orderterm = cmeth(attr, var.name)
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   411
                    if orderterm is not None:
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   412
                        try:
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   413
                            var, order = orderterm.split()
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   414
                        except ValueError:
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   415
                            if '(' in orderterm:
7963
059914a691a9 [entity] fix dumb name error introduced by 3.14 entity refactoring
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7920
diff changeset
   416
                                cls.error('ignore %s until %s is upgraded',
059914a691a9 [entity] fix dumb name error introduced by 3.14 entity refactoring
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7920
diff changeset
   417
                                          orderterm, cmeth)
7827
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   418
                                orderterm = None
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   419
                            elif not ' ' in orderterm.strip():
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   420
                                var = orderterm
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   421
                                order = 'ASC'
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   422
                        if orderterm is not None:
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   423
                            select.add_sort_var(select.get_variable(var),
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7816
diff changeset
   424
                                                order=='ASC')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   425
1471
c889c3bcf5ec new parent_classes method (cached)
sylvain.thenault@logilab.fr
parents: 1435
diff changeset
   426
    @classmethod
c889c3bcf5ec new parent_classes method (cached)
sylvain.thenault@logilab.fr
parents: 1435
diff changeset
   427
    @cached
7828
749e1a67987f [entity] rename Entity._rest_attr_info into cw_rest_attr_info (closes #1942759)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7827
diff changeset
   428
    def cw_rest_attr_info(cls):
749e1a67987f [entity] rename Entity._rest_attr_info into cw_rest_attr_info (closes #1942759)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7827
diff changeset
   429
        """this class method return an attribute name to be used in URL for
749e1a67987f [entity] rename Entity._rest_attr_info into cw_rest_attr_info (closes #1942759)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7827
diff changeset
   430
        entities of this type and a boolean flag telling if its value should be
749e1a67987f [entity] rename Entity._rest_attr_info into cw_rest_attr_info (closes #1942759)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7827
diff changeset
   431
        checked for uniqness.
749e1a67987f [entity] rename Entity._rest_attr_info into cw_rest_attr_info (closes #1942759)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7827
diff changeset
   432
749e1a67987f [entity] rename Entity._rest_attr_info into cw_rest_attr_info (closes #1942759)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7827
diff changeset
   433
        The attribute returned is, in order of priority:
749e1a67987f [entity] rename Entity._rest_attr_info into cw_rest_attr_info (closes #1942759)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7827
diff changeset
   434
749e1a67987f [entity] rename Entity._rest_attr_info into cw_rest_attr_info (closes #1942759)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7827
diff changeset
   435
        * class's `rest_attr` class attribute
749e1a67987f [entity] rename Entity._rest_attr_info into cw_rest_attr_info (closes #1942759)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7827
diff changeset
   436
        * an attribute defined as unique in the class'schema
749e1a67987f [entity] rename Entity._rest_attr_info into cw_rest_attr_info (closes #1942759)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7827
diff changeset
   437
        * 'eid'
749e1a67987f [entity] rename Entity._rest_attr_info into cw_rest_attr_info (closes #1942759)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7827
diff changeset
   438
        """
1840
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   439
        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
   440
        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
   441
            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
   442
            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
   443
        else:
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   444
            for rschema in cls.e_schema.subject_relations():
7828
749e1a67987f [entity] rename Entity._rest_attr_info into cw_rest_attr_info (closes #1942759)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7827
diff changeset
   445
                if rschema.final and rschema != 'eid' \
749e1a67987f [entity] rename Entity._rest_attr_info into cw_rest_attr_info (closes #1942759)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7827
diff changeset
   446
                        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
   447
                    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
   448
                    needcheck = False
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   449
                    break
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   450
        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
   451
            needcheck = False
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   452
        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
   453
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
   454
    @classmethod
8483
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
   455
    def _cw_build_entity_query(cls, kwargs):
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
   456
        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
   457
        restrictions = set()
8493
25da1e5c7c50 [entity/hooks] fix regression introduced by 4ba11607d84a
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8483
diff changeset
   458
        pendingrels = []
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
   459
        eschema = cls.e_schema
7376
38524ca653e5 [entity] fix cw_instantiate w/ reverse_ relation crash when either multiple entities are given or an eid instead of an entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7308
diff changeset
   460
        qargs = {}
8483
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
   461
        attrcache = {}
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
   462
        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
   463
            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
   464
                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
   465
                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
   466
            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
   467
                role = 'subject'
7287
601ad29268ab [entity] improve error message
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 7213
diff changeset
   468
            assert eschema.has_relation(attr, role), '%s %s not found on %s' % (attr, role, eschema)
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
   469
            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
   470
            if not rschema.final and isinstance(value, (tuple, list, set, frozenset)):
8199
fb5c0e60a615 [entity] fix crash when using cw_instantiate with empty related entity list; closes #2094462
Florent Cayré <florent.cayre@gmail.com>
parents: 7995
diff changeset
   471
                if len(value) == 0:
fb5c0e60a615 [entity] fix crash when using cw_instantiate with empty related entity list; closes #2094462
Florent Cayré <florent.cayre@gmail.com>
parents: 7995
diff changeset
   472
                    continue # avoid crash with empty IN clause
fb5c0e60a615 [entity] fix crash when using cw_instantiate with empty related entity list; closes #2094462
Florent Cayré <florent.cayre@gmail.com>
parents: 7995
diff changeset
   473
                elif len(value) == 1:
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
   474
                    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
   475
                else:
7213
7644e68c4e9f [entities] fix cw_instantiate typo
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7210
diff changeset
   476
                    # prepare IN clause
8493
25da1e5c7c50 [entity/hooks] fix regression introduced by 4ba11607d84a
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8483
diff changeset
   477
                    pendingrels.append( (attr, role, value) )
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
   478
                    continue
7376
38524ca653e5 [entity] fix cw_instantiate w/ reverse_ relation crash when either multiple entities are given or an eid instead of an entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7308
diff changeset
   479
            if rschema.final: # attribute
38524ca653e5 [entity] fix cw_instantiate w/ reverse_ relation crash when either multiple entities are given or an eid instead of an entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7308
diff changeset
   480
                relations.append('X %s %%(%s)s' % (attr, attr))
8483
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
   481
                attrcache[attr] = value
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
   482
            elif value is None:
8493
25da1e5c7c50 [entity/hooks] fix regression introduced by 4ba11607d84a
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8483
diff changeset
   483
                pendingrels.append( (attr, role, value) )
7376
38524ca653e5 [entity] fix cw_instantiate w/ reverse_ relation crash when either multiple entities are given or an eid instead of an entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7308
diff changeset
   484
            else:
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
   485
                rvar = attr.upper()
7213
7644e68c4e9f [entities] fix cw_instantiate typo
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7210
diff changeset
   486
                if role == 'object':
7644e68c4e9f [entities] fix cw_instantiate typo
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7210
diff changeset
   487
                    relations.append('%s %s X' % (rvar, attr))
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
   488
                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
   489
                    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
   490
                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
   491
                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
   492
                    restrictions.add(restriction)
7376
38524ca653e5 [entity] fix cw_instantiate w/ reverse_ relation crash when either multiple entities are given or an eid instead of an entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7308
diff changeset
   493
                if hasattr(value, 'eid'):
38524ca653e5 [entity] fix cw_instantiate w/ reverse_ relation crash when either multiple entities are given or an eid instead of an entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7308
diff changeset
   494
                    value = value.eid
38524ca653e5 [entity] fix cw_instantiate w/ reverse_ relation crash when either multiple entities are given or an eid instead of an entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7308
diff changeset
   495
            qargs[attr] = value
8483
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
   496
        rql = u''
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
   497
        if relations:
8483
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
   498
            rql += ', '.join(relations)
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
   499
        if restrictions:
8483
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
   500
            rql += ' WHERE %s' % ', '.join(restrictions)
8493
25da1e5c7c50 [entity/hooks] fix regression introduced by 4ba11607d84a
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8483
diff changeset
   501
        return rql, qargs, pendingrels, attrcache
8483
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
   502
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
   503
    @classmethod
8493
25da1e5c7c50 [entity/hooks] fix regression introduced by 4ba11607d84a
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8483
diff changeset
   504
    def _cw_handle_pending_relations(cls, eid, pendingrels, execute):
25da1e5c7c50 [entity/hooks] fix regression introduced by 4ba11607d84a
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8483
diff changeset
   505
        for attr, role, values in pendingrels:
7376
38524ca653e5 [entity] fix cw_instantiate w/ reverse_ relation crash when either multiple entities are given or an eid instead of an entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7308
diff changeset
   506
            if role == 'object':
38524ca653e5 [entity] fix cw_instantiate w/ reverse_ relation crash when either multiple entities are given or an eid instead of an entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7308
diff changeset
   507
                restr = 'Y %s X' % attr
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
   508
            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
   509
                restr = 'X %s Y' % attr
8483
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
   510
            if values is None:
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
   511
                execute('DELETE %s WHERE X eid %%(x)s' % restr, {'x': eid})
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
   512
                continue
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
   513
            execute('SET %s WHERE X eid %%(x)s, Y eid IN (%s)' % (
7376
38524ca653e5 [entity] fix cw_instantiate w/ reverse_ relation crash when either multiple entities are given or an eid instead of an entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7308
diff changeset
   514
                restr, ','.join(str(getattr(r, 'eid', r)) for r in values)),
8483
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
   515
                    {'x': eid}, build_descr=False)
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
   516
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
   517
    @classmethod
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
   518
    def cw_instantiate(cls, execute, **kwargs):
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
   519
        """add a new entity of this given type
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
   520
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
   521
        Example (in a shell session):
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
   522
8705
5b3e17a63fad Correct typo in example
Jérôme Roy <jerome.roy@logilab.fr>
parents: 8697
diff changeset
   523
        >>> companycls = vreg['etypes'].etype_class('Company')
5b3e17a63fad Correct typo in example
Jérôme Roy <jerome.roy@logilab.fr>
parents: 8697
diff changeset
   524
        >>> personcls = vreg['etypes'].etype_class('Person')
8483
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
   525
        >>> c = companycls.cw_instantiate(session.execute, name=u'Logilab')
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
   526
        >>> p = personcls.cw_instantiate(session.execute, firstname=u'John', lastname=u'Doe',
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
   527
        ...                              works_for=c)
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
   528
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
   529
        You can also set relations where the entity has 'object' role by
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
   530
        prefixing the relation name by 'reverse_'. Also, relation values may be
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
   531
        an entity or eid, a list of entities or eids.
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
   532
        """
8493
25da1e5c7c50 [entity/hooks] fix regression introduced by 4ba11607d84a
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8483
diff changeset
   533
        rql, qargs, pendingrels, attrcache = cls._cw_build_entity_query(kwargs)
8483
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
   534
        if rql:
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
   535
            rql = 'INSERT %s X: %s' % (cls.__regid__, rql)
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
   536
        else:
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
   537
            rql = 'INSERT %s X' % (cls.__regid__)
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
   538
        created = execute(rql, qargs).get_entity(0, 0)
8493
25da1e5c7c50 [entity/hooks] fix regression introduced by 4ba11607d84a
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8483
diff changeset
   539
        created._cw_update_attr_cache(attrcache)
25da1e5c7c50 [entity/hooks] fix regression introduced by 4ba11607d84a
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8483
diff changeset
   540
        cls._cw_handle_pending_relations(created.eid, pendingrels, execute)
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
   541
        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
   542
1435
6cd6172718bb allow to instantiate an entity without rset
sylvain.thenault@logilab.fr
parents: 1363
diff changeset
   543
    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
   544
        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
   545
        self._cw_related_cache = {}
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   546
        if rset is not None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   547
            self.eid = rset[row][col]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   548
        else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   549
            self.eid = None
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   550
        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
   551
        self.cw_attr_cache = {}
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   552
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   553
    def __repr__(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   554
        return '<Entity %s %s %s at %s>' % (
8696
0bb18407c053 [toward py3k] rewrite dict.keys() and dict.values() (part of #2711624)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 8661
diff changeset
   555
            self.e_schema, self.eid, list(self.cw_attr_cache), id(self))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   556
8892
80783605d270 [toward-py3k] rewrite __cmp__ (closes #2715115)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 8793
diff changeset
   557
    def __lt__(self, other):
80783605d270 [toward-py3k] rewrite __cmp__ (closes #2715115)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 8793
diff changeset
   558
        raise NotImplementedError('comparison not implemented for %s' % self.__class__)
80783605d270 [toward-py3k] rewrite __cmp__ (closes #2715115)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 8793
diff changeset
   559
80783605d270 [toward-py3k] rewrite __cmp__ (closes #2715115)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 8793
diff changeset
   560
    def __eq__(self, other):
6142
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
   561
        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
   562
8493
25da1e5c7c50 [entity/hooks] fix regression introduced by 4ba11607d84a
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8483
diff changeset
   563
    def _cw_update_attr_cache(self, attrcache):
8525
c09feae04094 [entity edition] don't remove values from attribute cache on the repository side
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8509
diff changeset
   564
        # if context is a repository session, don't consider dont-cache-attrs as
c09feae04094 [entity edition] don't remove values from attribute cache on the repository side
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8509
diff changeset
   565
        # the instance already hold modified values and loosing them could
c09feae04094 [entity edition] don't remove values from attribute cache on the repository side
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8509
diff changeset
   566
        # introduce severe problems
8661
4d24ac49f90d [entity] add a "repo_side" parameter to `_cw_dont_cache_attribute`
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 8660
diff changeset
   567
        get_set = partial(self._cw.get_shared_data, default=(), txdata=True,
4d24ac49f90d [entity] add a "repo_side" parameter to `_cw_dont_cache_attribute`
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 8660
diff changeset
   568
                          pop=True)
4d24ac49f90d [entity] add a "repo_side" parameter to `_cw_dont_cache_attribute`
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 8660
diff changeset
   569
        uncached_attrs = set()
4d24ac49f90d [entity] add a "repo_side" parameter to `_cw_dont_cache_attribute`
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 8660
diff changeset
   570
        uncached_attrs.update(get_set('%s.storage-special-process-attrs' % self.eid))
8525
c09feae04094 [entity edition] don't remove values from attribute cache on the repository side
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8509
diff changeset
   571
        if self._cw.is_request:
8661
4d24ac49f90d [entity] add a "repo_side" parameter to `_cw_dont_cache_attribute`
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 8660
diff changeset
   572
            uncached_attrs.update(get_set('%s.dont-cache-attrs' % self.eid))
4d24ac49f90d [entity] add a "repo_side" parameter to `_cw_dont_cache_attribute`
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 8660
diff changeset
   573
        for attr in uncached_attrs:
4d24ac49f90d [entity] add a "repo_side" parameter to `_cw_dont_cache_attribute`
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 8660
diff changeset
   574
            attrcache.pop(attr, None)
4d24ac49f90d [entity] add a "repo_side" parameter to `_cw_dont_cache_attribute`
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 8660
diff changeset
   575
            self.cw_attr_cache.pop(attr, None)
8493
25da1e5c7c50 [entity/hooks] fix regression introduced by 4ba11607d84a
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8483
diff changeset
   576
        self.cw_attr_cache.update(attrcache)
25da1e5c7c50 [entity/hooks] fix regression introduced by 4ba11607d84a
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8483
diff changeset
   577
8661
4d24ac49f90d [entity] add a "repo_side" parameter to `_cw_dont_cache_attribute`
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 8660
diff changeset
   578
    def _cw_dont_cache_attribute(self, attr, repo_side=False):
4d24ac49f90d [entity] add a "repo_side" parameter to `_cw_dont_cache_attribute`
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 8660
diff changeset
   579
        """Repository side method called when some attribute has been
8493
25da1e5c7c50 [entity/hooks] fix regression introduced by 4ba11607d84a
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8483
diff changeset
   580
        transformed by a hook, hence original value should not be cached by
8661
4d24ac49f90d [entity] add a "repo_side" parameter to `_cw_dont_cache_attribute`
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 8660
diff changeset
   581
        the client.
4d24ac49f90d [entity] add a "repo_side" parameter to `_cw_dont_cache_attribute`
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 8660
diff changeset
   582
4d24ac49f90d [entity] add a "repo_side" parameter to `_cw_dont_cache_attribute`
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 8660
diff changeset
   583
        If repo_side is True, this means that the attribute has been
4d24ac49f90d [entity] add a "repo_side" parameter to `_cw_dont_cache_attribute`
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 8660
diff changeset
   584
        transformed by a *storage*, hence the original value should
4d24ac49f90d [entity] add a "repo_side" parameter to `_cw_dont_cache_attribute`
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 8660
diff changeset
   585
        not be cached **by anyone**.
4d24ac49f90d [entity] add a "repo_side" parameter to `_cw_dont_cache_attribute`
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 8660
diff changeset
   586
4d24ac49f90d [entity] add a "repo_side" parameter to `_cw_dont_cache_attribute`
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 8660
diff changeset
   587
        This only applies to a storage special case where the value
4d24ac49f90d [entity] add a "repo_side" parameter to `_cw_dont_cache_attribute`
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 8660
diff changeset
   588
        specified in creation or update is **not** the value that will
4d24ac49f90d [entity] add a "repo_side" parameter to `_cw_dont_cache_attribute`
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 8660
diff changeset
   589
        be transparently exposed later.
4d24ac49f90d [entity] add a "repo_side" parameter to `_cw_dont_cache_attribute`
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 8660
diff changeset
   590
4d24ac49f90d [entity] add a "repo_side" parameter to `_cw_dont_cache_attribute`
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 8660
diff changeset
   591
        For example we have a special "fs_importing" mode in BFSS
4d24ac49f90d [entity] add a "repo_side" parameter to `_cw_dont_cache_attribute`
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 8660
diff changeset
   592
        where a file path is given as attribute value and stored as is
4d24ac49f90d [entity] add a "repo_side" parameter to `_cw_dont_cache_attribute`
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 8660
diff changeset
   593
        in the data base. Later access to the attribute will provide
4d24ac49f90d [entity] add a "repo_side" parameter to `_cw_dont_cache_attribute`
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 8660
diff changeset
   594
        the content of the file at the specified path. We do not want
4d24ac49f90d [entity] add a "repo_side" parameter to `_cw_dont_cache_attribute`
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 8660
diff changeset
   595
        the "filepath" value to be cached.
8493
25da1e5c7c50 [entity/hooks] fix regression introduced by 4ba11607d84a
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8483
diff changeset
   596
        """
25da1e5c7c50 [entity/hooks] fix regression introduced by 4ba11607d84a
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8483
diff changeset
   597
        self._cw.transaction_data.setdefault('%s.dont-cache-attrs' % self.eid, set()).add(attr)
8661
4d24ac49f90d [entity] add a "repo_side" parameter to `_cw_dont_cache_attribute`
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 8660
diff changeset
   598
        if repo_side:
4d24ac49f90d [entity] add a "repo_side" parameter to `_cw_dont_cache_attribute`
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 8660
diff changeset
   599
            trdata = self._cw.transaction_data
4d24ac49f90d [entity] add a "repo_side" parameter to `_cw_dont_cache_attribute`
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 8660
diff changeset
   600
            trdata.setdefault('%s.storage-special-process-attrs' % self.eid, set()).add(attr)
8493
25da1e5c7c50 [entity/hooks] fix regression introduced by 4ba11607d84a
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8483
diff changeset
   601
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
   602
    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
   603
        """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
   604
        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
   605
        """
7876
df15d194a134 [views] implement json / jsonp export views (closes #1942658)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7828
diff changeset
   606
        dumpable = self.cw_attr_cache.copy()
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
   607
        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
   608
        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
   609
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   610
    def cw_adapt_to(self, interface):
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   611
        """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
   612
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   613
        return None if it can not be adapted.
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   614
        """
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   615
        try:
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   616
            cache = self._cw_adapters_cache
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   617
        except AttributeError:
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   618
            self._cw_adapters_cache = cache = {}
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   619
        try:
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   620
            return cache[interface]
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   621
        except KeyError:
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   622
            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
   623
                interface, self._cw, entity=self)
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   624
            cache[interface] = adapter
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   625
            return adapter
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   626
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   627
    def has_eid(self): # XXX cw_has_eid
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   628
        """return True if the entity has an attributed eid (False
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   629
        meaning that the entity has to be created
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   630
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   631
        try:
8748
f5027f8d2478 drop typed_eid() in favour of int() (closes #2742462)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 8735
diff changeset
   632
            int(self.eid)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   633
            return True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   634
        except (ValueError, TypeError):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   635
            return False
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   636
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   637
    def cw_is_saved(self):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   638
        """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
   639
        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
   640
        '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
   641
        has an eid *and* is saved in its source.
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   642
        """
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   643
        return self.has_eid() and self._cw_is_saved
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   644
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   645
    @cached
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   646
    def cw_metainformation(self):
7543
570522300e22 [ms, entity metas] add 'actual source' to entities table / base entity metadata cache. Closes #1767090
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7514
diff changeset
   647
        res = self._cw.describe(self.eid, asdict=True)
570522300e22 [ms, entity metas] add 'actual source' to entities table / base entity metadata cache. Closes #1767090
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7514
diff changeset
   648
        # use 'asource' and not 'source' since this is the actual source,
570522300e22 [ms, entity metas] add 'actual source' to entities table / base entity metadata cache. Closes #1767090
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7514
diff changeset
   649
        # while 'source' is the physical source (where it's stored)
570522300e22 [ms, entity metas] add 'actual source' to entities table / base entity metadata cache. Closes #1767090
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7514
diff changeset
   650
        res['source'] = self._cw.source_defs()[res.pop('asource')]
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   651
        return res
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   652
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   653
    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
   654
        self.e_schema.check_perm(self._cw, action, eid=self.eid)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   655
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   656
    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
   657
        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
   658
6085
8a059eefac75 [entity] entity.view now support initargs as req.view
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5980
diff changeset
   659
    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
   660
        """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
   661
        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
   662
            initargs = kwargs
8a059eefac75 [entity] entity.view now support initargs as req.view
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5980
diff changeset
   663
        else:
8a059eefac75 [entity] entity.view now support initargs as req.view
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5980
diff changeset
   664
            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
   665
        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
   666
                                                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
   667
                                                **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
   668
        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
   669
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   670
    def absolute_url(self, *args, **kwargs): # XXX cw_url
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   671
        """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
   672
        # 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
   673
        # 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
   674
        if args:
af33833d7571 absolute_url / build_url refactoring to avoid potential name clash
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2058
diff changeset
   675
            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
   676
            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
   677
        else:
af33833d7571 absolute_url / build_url refactoring to avoid potential name clash
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2058
diff changeset
   678
            method = None
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   679
        # in linksearch mode, we don't want external urls else selecting
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   680
        # the object for use in the relation is tricky
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   681
        # 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
   682
        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
   683
        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
   684
               getattr(self._cw, 'search_state', ('normal',))[0] == 'normal':
7552
82dde8276a5b [datafeed, entities] url for entities from a datafeed source should be on their origin site. Closes #1769391
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7543
diff changeset
   685
            sourcemeta = self.cw_metainformation()['source']
82dde8276a5b [datafeed, entities] url for entities from a datafeed source should be on their origin site. Closes #1769391
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7543
diff changeset
   686
            if sourcemeta.get('use-cwuri-as-url'):
82dde8276a5b [datafeed, entities] url for entities from a datafeed source should be on their origin site. Closes #1769391
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7543
diff changeset
   687
                return self.cwuri # XXX consider kwargs?
82dde8276a5b [datafeed, entities] url for entities from a datafeed source should be on their origin site. Closes #1769391
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7543
diff changeset
   688
            if sourcemeta.get('base-url'):
82dde8276a5b [datafeed, entities] url for entities from a datafeed source should be on their origin site. Closes #1769391
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7543
diff changeset
   689
                kwargs['base_url'] = sourcemeta['base-url']
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
   690
                use_ext_id = True
1904
e23536d29231 minor refactoring of absolute_url()
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 1842
diff changeset
   691
        if method in (None, 'view'):
7990
a673d1d9a738 [diet] drop pre 3.6 API compatibility (but attempt to keep data cmopatibility). Closes #2017916
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7973
diff changeset
   692
            kwargs['_restpath'] = self.rest_path(use_ext_id)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   693
        else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   694
            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
   695
        return self._cw.build_url(method, **kwargs)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   696
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   697
    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
   698
        """returns a REST-like (relative) path for this entity"""
7828
749e1a67987f [entity] rename Entity._rest_attr_info into cw_rest_attr_info (closes #1942759)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7827
diff changeset
   699
        mainattr, needcheck = self.cw_rest_attr_info()
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   700
        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
   701
        path = etype.lower()
8286
8b0146e31baa [entity url] rest path fallback should be the url used as cwuri. Closes #2186039
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8199
diff changeset
   702
        fallback = False
1840
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   703
        if mainattr != 'eid':
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   704
            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
   705
            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
   706
                mainattr = 'eid'
8286
8b0146e31baa [entity url] rest path fallback should be the url used as cwuri. Closes #2186039
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8199
diff changeset
   707
                path = None
1840
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   708
            elif needcheck:
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   709
                # 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
   710
                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
   711
                    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
   712
                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
   713
                    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
   714
                        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
   715
                    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
   716
                if nbresults != 1: # ambiguity?
e23536d29231 minor refactoring of absolute_url()
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 1842
diff changeset
   717
                    mainattr = 'eid'
8286
8b0146e31baa [entity url] rest path fallback should be the url used as cwuri. Closes #2186039
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8199
diff changeset
   718
                    path = None
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   719
        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
   720
            if use_ext_eid:
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   721
                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
   722
            else:
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   723
                value = self.eid
8286
8b0146e31baa [entity url] rest path fallback should be the url used as cwuri. Closes #2186039
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8199
diff changeset
   724
        if path is None:
8b0146e31baa [entity url] rest path fallback should be the url used as cwuri. Closes #2186039
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8199
diff changeset
   725
            # fallback url: <base-url>/<eid> url is used as cw entities uri,
8b0146e31baa [entity url] rest path fallback should be the url used as cwuri. Closes #2186039
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8199
diff changeset
   726
            # prefer it to <base-url>/<etype>/eid/<eid>
8b0146e31baa [entity url] rest path fallback should be the url used as cwuri. Closes #2186039
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8199
diff changeset
   727
            return unicode(value)
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   728
        return '%s/%s' % (path, self._cw.url_quote(value))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   729
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   730
    def cw_attr_metadata(self, attr, metadata):
1101
0c067de38e46 unification of meta-attributes handling:
sylvain.thenault@logilab.fr
parents: 1098
diff changeset
   731
        """return a metadata for an attribute (None if unspecified)"""
0c067de38e46 unification of meta-attributes handling:
sylvain.thenault@logilab.fr
parents: 1098
diff changeset
   732
        value = getattr(self, '%s_%s' % (attr, metadata), None)
0c067de38e46 unification of meta-attributes handling:
sylvain.thenault@logilab.fr
parents: 1098
diff changeset
   733
        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
   734
            value = self._cw.vreg.property_value('ui.encoding')
1101
0c067de38e46 unification of meta-attributes handling:
sylvain.thenault@logilab.fr
parents: 1098
diff changeset
   735
        return value
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   736
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   737
    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
   738
                        format='text/html', displaytime=True): # XXX cw_printable_value
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   739
        """return a displayable value (i.e. unicode string) which may contains
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   740
        html tags
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   741
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   742
        attr = str(attr)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   743
        if value is _marker:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   744
            value = getattr(self, attr)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   745
        if isinstance(value, basestring):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   746
            value = value.strip()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   747
        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
   748
            return u''
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   749
        if attrtype is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   750
            attrtype = self.e_schema.destination(attr)
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   751
        props = self.e_schema.rdef(attr)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   752
        if attrtype == 'String':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   753
            # internalinalized *and* formatted string such as schema
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   754
            # description...
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   755
            if props.internationalizable:
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   756
                value = self._cw._(value)
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   757
            attrformat = self.cw_attr_metadata(attr, 'format')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   758
            if attrformat:
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   759
                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
   760
                                              self._cw.encoding)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   761
        elif attrtype == 'Bytes':
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   762
            attrformat = self.cw_attr_metadata(attr, 'format')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   763
            if attrformat:
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   764
                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
   765
                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
   766
                                              encoding)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   767
            return u''
7914
fb757a7d887e [request, ui] printable_value is now a method of request, and may be given dict of formatters to use (closes #1984743)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7907
diff changeset
   768
        value = self._cw.printable_value(attrtype, value, props,
fb757a7d887e [request, ui] printable_value is now a method of request, and may be given dict of formatters to use (closes #1984743)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7907
diff changeset
   769
                                         displaytime=displaytime)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   770
        if format == 'text/html':
2312
af4d8f75c5db use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2125
diff changeset
   771
            value = xml_escape(value)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   772
        return value
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   773
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   774
    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
   775
                          _engine=ENGINE):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   776
        trdata = TransformData(data, format, encoding, appobject=self)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   777
        data = _engine.convert(trdata, target_format).decode()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   778
        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
   779
            data = soup2xhtml(data, self._cw.encoding)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   780
        return data
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   781
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   782
    # entity cloning ##########################################################
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   783
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   784
    def copy_relations(self, ceid): # XXX cw_copy_relations
3626
017869a514c3 [doc] updated docstrings
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 3552
diff changeset
   785
        """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
   786
        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
   787
        ceid designates the original entity).
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   788
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   789
        By default meta and composite relations are skipped.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   790
        Overrides this if you want another behaviour
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   791
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   792
        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
   793
        execute = self._cw.execute
7702
73cadb5d0097 [entities] skip_copy_for should be considered for object relations too (closes #1857474)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7552
diff changeset
   794
        skip_copy_for = {'subject': set(), 'object': set()}
73cadb5d0097 [entities] skip_copy_for should be considered for object relations too (closes #1857474)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7552
diff changeset
   795
        for rtype in self.skip_copy_for:
73cadb5d0097 [entities] skip_copy_for should be considered for object relations too (closes #1857474)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7552
diff changeset
   796
            skip_copy_for['subject'].add(rtype)
73cadb5d0097 [entities] skip_copy_for should be considered for object relations too (closes #1857474)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7552
diff changeset
   797
            warn('[3.14] skip_copy_for on entity classes (%s) is deprecated, '
8900
010a59e12d89 use cw_etype instead of __regid__
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 8793
diff changeset
   798
                 'use cw_skip_for instead with list of couples (rtype, role)' % self.cw_etype,
7702
73cadb5d0097 [entities] skip_copy_for should be considered for object relations too (closes #1857474)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7552
diff changeset
   799
                 DeprecationWarning)
73cadb5d0097 [entities] skip_copy_for should be considered for object relations too (closes #1857474)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7552
diff changeset
   800
        for rtype, role in self.cw_skip_copy_for:
73cadb5d0097 [entities] skip_copy_for should be considered for object relations too (closes #1857474)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7552
diff changeset
   801
            assert role in ('subject', 'object'), role
73cadb5d0097 [entities] skip_copy_for should be considered for object relations too (closes #1857474)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7552
diff changeset
   802
            skip_copy_for[role].add(rtype)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   803
        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
   804
            if rschema.final or rschema.meta:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   805
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   806
            # skip already defined relations
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   807
            if getattr(self, rschema.type):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   808
                continue
7702
73cadb5d0097 [entities] skip_copy_for should be considered for object relations too (closes #1857474)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7552
diff changeset
   809
            if rschema.type in skip_copy_for['subject']:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   810
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   811
            # skip composite relation
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   812
            rdef = self.e_schema.rdef(rschema)
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   813
            if rdef.composite:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   814
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   815
            # skip relation with card in ?1 else we either change the copied
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   816
            # object (inlined relation) or inserting some inconsistency
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   817
            if rdef.cardinality[1] in '?1':
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   818
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   819
            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
   820
                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
   821
            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
   822
            self.cw_clear_relation_cache(rschema.type, 'subject')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   823
        for rschema in self.e_schema.object_relations():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   824
            if rschema.meta:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   825
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   826
            # skip already defined relations
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   827
            if self.related(rschema.type, 'object'):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   828
                continue
7702
73cadb5d0097 [entities] skip_copy_for should be considered for object relations too (closes #1857474)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7552
diff changeset
   829
            if rschema.type in skip_copy_for['object']:
73cadb5d0097 [entities] skip_copy_for should be considered for object relations too (closes #1857474)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7552
diff changeset
   830
                continue
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   831
            rdef = self.e_schema.rdef(rschema, 'object')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   832
            # skip composite relation
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   833
            if rdef.composite:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   834
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   835
            # skip relation with card in ?1 else we either change the copied
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   836
            # object (inlined relation) or inserting some inconsistency
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   837
            if rdef.cardinality[0] in '?1':
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   838
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   839
            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
   840
                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
   841
            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
   842
            self.cw_clear_relation_cache(rschema.type, 'object')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   843
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   844
    # data fetching methods ###################################################
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   845
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   846
    @cached
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   847
    def as_rset(self): # XXX .cw_as_rset
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   848
        """returns a resultset containing `self` information"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   849
        rset = ResultSet([(self.eid,)], 'Any X WHERE X eid %(x)s',
8900
010a59e12d89 use cw_etype instead of __regid__
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 8793
diff changeset
   850
                         {'x': self.eid}, [(self.cw_etype,)])
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
   851
        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
   852
        return rset
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   853
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   854
    def _cw_to_complete_relations(self):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   855
        """by default complete final relations to when calling .complete()"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   856
        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
   857
            if rschema.final:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   858
                continue
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   859
            targets = rschema.objects(self.e_schema)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   860
            if rschema.inlined:
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   861
                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
   862
                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
   863
                       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
   864
                       for e in targets):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   865
                    yield rschema, 'subject'
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   866
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   867
    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
   868
        for rschema, attrschema in self.e_schema.attribute_definitions():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   869
            # skip binary data by default
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   870
            if skip_bytes and attrschema.type == 'Bytes':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   871
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   872
            attr = rschema.type
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   873
            if attr == 'eid':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   874
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   875
            # password retreival is blocked at the repository server level
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   876
            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
   877
            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
   878
                   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
   879
                self.cw_attr_cache[attr] = None
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   880
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   881
            yield attr
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   882
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
   883
    _cw_completed = False
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   884
    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
   885
        """complete this entity by adding missing attributes (i.e. query the
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   886
        repository to fill the entity)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   887
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   888
        :type skip_bytes: bool
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   889
        :param skip_bytes:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   890
          if true, attribute of type Bytes won't be considered
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   891
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   892
        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
   893
        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
   894
            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
   895
        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
   896
            self._cw_completed = True
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   897
        varmaker = rqlvar_maker()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   898
        V = varmaker.next()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   899
        rql = ['WHERE %s eid %%(x)s' % V]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   900
        selected = []
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   901
        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
   902
            # if attribute already in entity, nothing to do
8697
574bb05e40a4 [toward py3k] rewrite has_key() (part of #2711624)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 8696
diff changeset
   903
            if attr in self.cw_attr_cache:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   904
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   905
            # case where attribute must be completed, but is not yet in entity
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   906
            var = varmaker.next()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   907
            rql.append('%s %s %s' % (V, attr, var))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   908
            selected.append((attr, var))
7995
9a9f35ef418c Record a log of datafeed source imports (closes #2026097)
Julien Cristau <julien.cristau@logilab.fr>
parents: 7990
diff changeset
   909
        # +1 since this doesn't include the main variable
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   910
        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
   911
        # 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
   912
        # 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
   913
        if attributes is None and self.cw_metainformation()['source']['uri'] == 'system':
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   914
            # 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
   915
            for rschema, role in self._cw_to_complete_relations():
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   916
                rtype = rschema.type
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   917
                if self.cw_relation_cached(rtype, role):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   918
                    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
   919
                # 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
   920
                # * 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
   921
                # * 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
   922
                # * 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
   923
                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
   924
                assert role == 'subject'
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   925
                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
   926
                # 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
   927
                # 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
   928
                rql.append('%s %s %s?' % (V, rtype, var))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   929
                selected.append(((rtype, role), var))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   930
        if selected:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   931
            # select V, we need it as the left most selected variable
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   932
            # if some outer join are included to fetch inlined relations
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   933
            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
   934
                                    ','.join(rql))
6656
bea4ab297e67 [ms entity] proper error on external entity fetch error
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6499
diff changeset
   935
            try:
bea4ab297e67 [ms entity] proper error on external entity fetch error
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6499
diff changeset
   936
                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
   937
            except IndexError:
bea4ab297e67 [ms entity] proper error on external entity fetch error
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6499
diff changeset
   938
                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
   939
                                % self.eid)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   940
            # handle attributes
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   941
            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
   942
                self.cw_attr_cache[str(selected[i-1][0])] = rset[i]
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   943
            # handle relations
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   944
            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
   945
                rtype, role = selected[i-1][0]
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   946
                value = rset[i]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   947
                if value is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   948
                    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
   949
                    rrset.req = self._cw
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   950
                else:
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   951
                    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
   952
                self.cw_set_relation_cache(rtype, role, rrset)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   953
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   954
    def cw_attr_value(self, name):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   955
        """get value for the attribute relation <name>, query the repository
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   956
        to get the value if necessary.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   957
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   958
        :type name: str
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   959
        :param name: name of the attribute to get
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   960
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   961
        try:
6142
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
   962
            return self.cw_attr_cache[name]
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   963
        except KeyError:
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   964
            if not self.cw_is_saved():
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   965
                return None
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   966
            rql = "Any A WHERE X eid %%(x)s, X %s A" % name
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   967
            try:
5174
78438ad513ca #759035: Automate addition of eid cachekey in RQL analysis
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   968
                rset = self._cw.execute(rql, {'x': self.eid})
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   969
            except Unauthorized:
6142
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
   970
                self.cw_attr_cache[name] = value = None
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   971
            else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   972
                assert rset.rowcount <= 1, (self, rql, rset.rowcount)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   973
                try:
6142
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
   974
                    self.cw_attr_cache[name] = value = rset.rows[0][0]
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   975
                except IndexError:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   976
                    # probably a multisource error
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   977
                    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
   978
                                  name, self.eid)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   979
                    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
   980
                        self.cw_attr_cache[name] = value = self._cw._('unaccessible')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   981
                    else:
6142
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
   982
                        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
   983
            return value
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   984
7911
5ab88d05083f [xml/rdf views] handle case where the user hasn't read access to a relation (closes #1984598)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7899
diff changeset
   985
    def related(self, rtype, role='subject', limit=None, entities=False, # XXX .cw_related
5ab88d05083f [xml/rdf views] handle case where the user hasn't read access to a relation (closes #1984598)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7899
diff changeset
   986
                safe=False):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   987
        """returns a resultset of related entities
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   988
7911
5ab88d05083f [xml/rdf views] handle case where the user hasn't read access to a relation (closes #1984598)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7899
diff changeset
   989
        :param rtype:
5ab88d05083f [xml/rdf views] handle case where the user hasn't read access to a relation (closes #1984598)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7899
diff changeset
   990
          the name of the relation, aka relation type
5ab88d05083f [xml/rdf views] handle case where the user hasn't read access to a relation (closes #1984598)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7899
diff changeset
   991
        :param role:
5ab88d05083f [xml/rdf views] handle case where the user hasn't read access to a relation (closes #1984598)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7899
diff changeset
   992
          the role played by 'self' in the relation ('subject' or 'object')
5ab88d05083f [xml/rdf views] handle case where the user hasn't read access to a relation (closes #1984598)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7899
diff changeset
   993
        :param limit:
5ab88d05083f [xml/rdf views] handle case where the user hasn't read access to a relation (closes #1984598)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7899
diff changeset
   994
          resultset's maximum size
5ab88d05083f [xml/rdf views] handle case where the user hasn't read access to a relation (closes #1984598)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7899
diff changeset
   995
        :param entities:
5ab88d05083f [xml/rdf views] handle case where the user hasn't read access to a relation (closes #1984598)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7899
diff changeset
   996
          if True, the entites are returned; if False, a result set is returned
5ab88d05083f [xml/rdf views] handle case where the user hasn't read access to a relation (closes #1984598)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7899
diff changeset
   997
        :param safe:
5ab88d05083f [xml/rdf views] handle case where the user hasn't read access to a relation (closes #1984598)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7899
diff changeset
   998
          if True, an empty rset/list of entities will be returned in case of
5ab88d05083f [xml/rdf views] handle case where the user hasn't read access to a relation (closes #1984598)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7899
diff changeset
   999
          :exc:`Unauthorized`, else (the default), the exception is propagated
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1000
        """
7794
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1001
        rtype = str(rtype)
8735
5567a5117aeb [entity] ensure the .related(entities=False) parameter is honored all the way down (closes #2755994)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8705
diff changeset
  1002
        if limit is None:
5567a5117aeb [entity] ensure the .related(entities=False) parameter is honored all the way down (closes #2755994)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8705
diff changeset
  1003
            # we cannot do much wrt cache on limited queries
5567a5117aeb [entity] ensure the .related(entities=False) parameter is honored all the way down (closes #2755994)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8705
diff changeset
  1004
            cache_key = '%s_%s' % (rtype, role)
5567a5117aeb [entity] ensure the .related(entities=False) parameter is honored all the way down (closes #2755994)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8705
diff changeset
  1005
            if cache_key in self._cw_related_cache:
5567a5117aeb [entity] ensure the .related(entities=False) parameter is honored all the way down (closes #2755994)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8705
diff changeset
  1006
                return self._cw_related_cache[cache_key][entities]
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
  1007
        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
  1008
            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
  1009
                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
  1010
            return self._cw.empty_rset()
8735
5567a5117aeb [entity] ensure the .related(entities=False) parameter is honored all the way down (closes #2755994)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8705
diff changeset
  1011
        rql = self.cw_related_rql(rtype, role, limit=limit)
7911
5ab88d05083f [xml/rdf views] handle case where the user hasn't read access to a relation (closes #1984598)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7899
diff changeset
  1012
        try:
5ab88d05083f [xml/rdf views] handle case where the user hasn't read access to a relation (closes #1984598)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7899
diff changeset
  1013
            rset = self._cw.execute(rql, {'x': self.eid})
5ab88d05083f [xml/rdf views] handle case where the user hasn't read access to a relation (closes #1984598)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7899
diff changeset
  1014
        except Unauthorized:
5ab88d05083f [xml/rdf views] handle case where the user hasn't read access to a relation (closes #1984598)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7899
diff changeset
  1015
            if not safe:
5ab88d05083f [xml/rdf views] handle case where the user hasn't read access to a relation (closes #1984598)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7899
diff changeset
  1016
                raise
5ab88d05083f [xml/rdf views] handle case where the user hasn't read access to a relation (closes #1984598)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7899
diff changeset
  1017
            rset = self._cw.empty_rset()
8735
5567a5117aeb [entity] ensure the .related(entities=False) parameter is honored all the way down (closes #2755994)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8705
diff changeset
  1018
        if entities:
5567a5117aeb [entity] ensure the .related(entities=False) parameter is honored all the way down (closes #2755994)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8705
diff changeset
  1019
            if limit is None:
5567a5117aeb [entity] ensure the .related(entities=False) parameter is honored all the way down (closes #2755994)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8705
diff changeset
  1020
                self.cw_set_relation_cache(rtype, role, rset)
5567a5117aeb [entity] ensure the .related(entities=False) parameter is honored all the way down (closes #2755994)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8705
diff changeset
  1021
                return self.related(rtype, role, limit, entities)
5567a5117aeb [entity] ensure the .related(entities=False) parameter is honored all the way down (closes #2755994)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8705
diff changeset
  1022
            return list(rset.entities())
5567a5117aeb [entity] ensure the .related(entities=False) parameter is honored all the way down (closes #2755994)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8705
diff changeset
  1023
        else:
5567a5117aeb [entity] ensure the .related(entities=False) parameter is honored all the way down (closes #2755994)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8705
diff changeset
  1024
            return rset
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1025
8735
5567a5117aeb [entity] ensure the .related(entities=False) parameter is honored all the way down (closes #2755994)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8705
diff changeset
  1026
    def cw_related_rql(self, rtype, role='subject', targettypes=None, limit=None):
7798
8930f7a284dd [entity fetchattrs] also fetch ambiguous rtypes even if we do not recurse on them (closes #1720823)
Florent Cayré <florent.cayre@gmail.com>
parents: 7794
diff changeset
  1027
        vreg = self._cw.vreg
8930f7a284dd [entity fetchattrs] also fetch ambiguous rtypes even if we do not recurse on them (closes #1720823)
Florent Cayré <florent.cayre@gmail.com>
parents: 7794
diff changeset
  1028
        rschema = vreg.schema[rtype]
7794
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1029
        select = Select()
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1030
        mainvar, evar = select.get_variable('X'), select.get_variable('E')
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1031
        select.add_selected(mainvar)
8735
5567a5117aeb [entity] ensure the .related(entities=False) parameter is honored all the way down (closes #2755994)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8705
diff changeset
  1032
        if limit is not None:
5567a5117aeb [entity] ensure the .related(entities=False) parameter is honored all the way down (closes #2755994)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8705
diff changeset
  1033
            select.set_limit(limit)
7794
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1034
        select.add_eid_restriction(evar, 'x', 'Substitute')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1035
        if role == 'subject':
7794
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1036
            rel = make_relation(evar, rtype, (mainvar,), VariableRef)
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1037
            select.add_restriction(rel)
3130
2486163c4630 allow to specify targettypes in related_rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3047
diff changeset
  1038
            if targettypes is None:
2486163c4630 allow to specify targettypes in related_rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3047
diff changeset
  1039
                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
  1040
            else:
7794
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1041
                select.add_constant_restriction(mainvar, 'is',
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1042
                                                targettypes, 'etype')
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1043
            gcard = greater_card(rschema, (self.e_schema,), targettypes, 0)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1044
        else:
7794
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1045
            rel = make_relation(mainvar, rtype, (evar,), VariableRef)
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1046
            select.add_restriction(rel)
3130
2486163c4630 allow to specify targettypes in related_rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3047
diff changeset
  1047
            if targettypes is None:
2486163c4630 allow to specify targettypes in related_rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3047
diff changeset
  1048
                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
  1049
            else:
7794
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1050
                select.add_constant_restriction(mainvar, 'is', targettypes,
7964
4ea2abc83dce [entity related rql] 'is' relation target constant should have 'etype' type, not String
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7963
diff changeset
  1051
                                                'etype')
7794
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1052
            gcard = greater_card(rschema, targettypes, (self.e_schema,), 1)
7798
8930f7a284dd [entity fetchattrs] also fetch ambiguous rtypes even if we do not recurse on them (closes #1720823)
Florent Cayré <florent.cayre@gmail.com>
parents: 7794
diff changeset
  1053
        etypecls = vreg['etypes'].etype_class(targettypes[0])
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1054
        if len(targettypes) > 1:
7798
8930f7a284dd [entity fetchattrs] also fetch ambiguous rtypes even if we do not recurse on them (closes #1720823)
Florent Cayré <florent.cayre@gmail.com>
parents: 7794
diff changeset
  1055
            fetchattrs = vreg['etypes'].fetch_attrs(targettypes)
8930f7a284dd [entity fetchattrs] also fetch ambiguous rtypes even if we do not recurse on them (closes #1720823)
Florent Cayré <florent.cayre@gmail.com>
parents: 7794
diff changeset
  1056
            self._fetch_ambiguous_rtypes(select, mainvar, fetchattrs,
8930f7a284dd [entity fetchattrs] also fetch ambiguous rtypes even if we do not recurse on them (closes #1720823)
Florent Cayré <florent.cayre@gmail.com>
parents: 7794
diff changeset
  1057
                                         targettypes, vreg.schema)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1058
        else:
7302
c281afe35b8b [entity] fix entity fetch_rql when fetch_attrs contains a rtype with multiple destination etypes which do not have the same fetched attributes themselves (closes #1631282)
Florent Cayré <florent.cayre@gmail.com>
parents: 7288
diff changeset
  1059
            fetchattrs = etypecls.fetch_attrs
7794
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1060
        etypecls.fetch_rqlst(self._cw.user, select, mainvar, fetchattrs,
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1061
                             settype=False)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1062
        # optimisation: remove ORDERBY if cardinality is 1 or ? (though
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1063
        # greater_card return 1 for those both cases)
7794
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1064
        if gcard == '1':
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1065
            select.remove_sort_terms()
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1066
        elif not select.orderby:
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1067
            # if modification_date is already retrieved, we use it instead
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1068
            # of adding another variable for sorting. This should not be
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1069
            # problematic, but it is with sqlserver, see ticket #694445
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1070
            for rel in select.where.get_nodes(RqlRelation):
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1071
                if (rel.r_type == 'modification_date'
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1072
                    and rel.children[0].variable == mainvar
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1073
                    and rel.children[1].operator == '='):
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1074
                    var = rel.children[1].children[0].variable
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1075
                    select.add_sort_var(var, asc=False)
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1076
                    break
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
  1077
            else:
7794
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1078
                mdvar = select.make_variable()
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1079
                rel = make_relation(mainvar, 'modification_date',
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1080
                                    (mdvar,), VariableRef)
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1081
                select.add_restriction(rel)
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1082
                select.add_sort_var(mdvar, asc=False)
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1083
        return select.as_string()
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
  1084
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1085
    # generic vocabulary methods ##############################################
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1086
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1087
    def cw_unrelated_rql(self, rtype, targettype, role, ordermethod=None,
8735
5567a5117aeb [entity] ensure the .related(entities=False) parameter is honored all the way down (closes #2755994)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8705
diff changeset
  1088
                         vocabconstraints=True, lt_infos={}, limit=None):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1089
        """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
  1090
        using (rtype, role) relation.
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
  1091
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
  1092
        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
  1093
        linked by `rtype`.
7973
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
  1094
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
  1095
        `lt_infos` are supplementary informations, usually coming from __linkto
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
  1096
        parameter, that can help further restricting the results in case current
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
  1097
        entity is not yet created. It is a dict describing entities the current
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
  1098
        entity will be linked to, which keys are (rtype, role) tuples and values
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
  1099
        are a list of eids.
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1100
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1101
        ordermethod = ordermethod or 'fetch_unrelated_order'
7973
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
  1102
        rschema = self._cw.vreg.schema.rschema(rtype)
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
  1103
        rdef = rschema.role_rdef(self.e_schema, targettype, role)
7154
5e2f93b88d86 [entity vocabulary] refactor unrelated rql to allow usage of RQLRewriter to insert schema constraints. Closes #1561806
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7153
diff changeset
  1104
        rewriter = RQLRewriter(self._cw)
7794
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1105
        select = Select()
7154
5e2f93b88d86 [entity vocabulary] refactor unrelated rql to allow usage of RQLRewriter to insert schema constraints. Closes #1561806
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7153
diff changeset
  1106
        # initialize some variables according to the `role` of `self` in the
7794
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1107
        # relation (variable names must respect constraints conventions):
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1108
        # * variable for myself (`evar`)
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1109
        # * variable for searched entities (`searchvedvar`)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1110
        if role == 'subject':
7794
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1111
            evar = subjvar = select.get_variable('S')
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1112
            searchedvar = objvar = select.get_variable('O')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1113
        else:
7794
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1114
            searchedvar = subjvar = select.get_variable('S')
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1115
            evar = objvar = select.get_variable('O')
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1116
        select.add_selected(searchedvar)
8735
5567a5117aeb [entity] ensure the .related(entities=False) parameter is honored all the way down (closes #2755994)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8705
diff changeset
  1117
        if limit is not None:
5567a5117aeb [entity] ensure the .related(entities=False) parameter is honored all the way down (closes #2755994)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8705
diff changeset
  1118
            select.set_limit(limit)
7973
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
  1119
        # initialize some variables according to `self` existence
7177
0f2905cbe443 [entity vocab] fix bug introduced in 3.12 vs/ entity vocabulary, leading to some unexpected empty vocabulary. Fix test accordingly.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7154
diff changeset
  1120
        if rdef.role_cardinality(neg_role(role)) in '?1':
0f2905cbe443 [entity vocab] fix bug introduced in 3.12 vs/ entity vocabulary, leading to some unexpected empty vocabulary. Fix test accordingly.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7154
diff changeset
  1121
            # if cardinality in '1?', we want a target entity which isn't
0f2905cbe443 [entity vocab] fix bug introduced in 3.12 vs/ entity vocabulary, leading to some unexpected empty vocabulary. Fix test accordingly.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7154
diff changeset
  1122
            # already linked using this relation
7973
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
  1123
            variable = select.make_variable()
7794
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1124
            if role == 'subject':
7973
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
  1125
                rel = make_relation(variable, rtype, (searchedvar,), VariableRef)
7177
0f2905cbe443 [entity vocab] fix bug introduced in 3.12 vs/ entity vocabulary, leading to some unexpected empty vocabulary. Fix test accordingly.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7154
diff changeset
  1126
            else:
7973
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
  1127
                rel = make_relation(searchedvar, rtype, (variable,), VariableRef)
7794
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1128
            select.add_restriction(Not(rel))
7177
0f2905cbe443 [entity vocab] fix bug introduced in 3.12 vs/ entity vocabulary, leading to some unexpected empty vocabulary. Fix test accordingly.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7154
diff changeset
  1129
        elif self.has_eid():
0f2905cbe443 [entity vocab] fix bug introduced in 3.12 vs/ entity vocabulary, leading to some unexpected empty vocabulary. Fix test accordingly.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7154
diff changeset
  1130
            # elif we have an eid, we don't want a target entity which is
0f2905cbe443 [entity vocab] fix bug introduced in 3.12 vs/ entity vocabulary, leading to some unexpected empty vocabulary. Fix test accordingly.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7154
diff changeset
  1131
            # already linked to ourself through this relation
7973
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
  1132
            rel = make_relation(subjvar, rtype, (objvar,), VariableRef)
7794
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1133
            select.add_restriction(Not(rel))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1134
        if self.has_eid():
7794
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1135
            rel = make_relation(evar, 'eid', ('x', 'Substitute'), Constant)
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1136
            select.add_restriction(rel)
3241
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
  1137
            args = {'x': self.eid}
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
  1138
            if role == 'subject':
7154
5e2f93b88d86 [entity vocabulary] refactor unrelated rql to allow usage of RQLRewriter to insert schema constraints. Closes #1561806
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7153
diff changeset
  1139
                sec_check_args = {'fromeid': self.eid}
3241
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
  1140
            else:
7154
5e2f93b88d86 [entity vocabulary] refactor unrelated rql to allow usage of RQLRewriter to insert schema constraints. Closes #1561806
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7153
diff changeset
  1141
                sec_check_args = {'toeid': self.eid}
5e2f93b88d86 [entity vocabulary] refactor unrelated rql to allow usage of RQLRewriter to insert schema constraints. Closes #1561806
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7153
diff changeset
  1142
            existant = None # instead of 'SO', improve perfs
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1143
        else:
3241
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
  1144
            args = {}
7154
5e2f93b88d86 [entity vocabulary] refactor unrelated rql to allow usage of RQLRewriter to insert schema constraints. Closes #1561806
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7153
diff changeset
  1145
            sec_check_args = {}
7794
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1146
            existant = searchedvar.name
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1147
            # undefine unused evar, or the type resolver will consider it
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1148
            select.undefine_variable(evar)
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1149
        # retrieve entity class for targettype to compute base rql
7154
5e2f93b88d86 [entity vocabulary] refactor unrelated rql to allow usage of RQLRewriter to insert schema constraints. Closes #1561806
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7153
diff changeset
  1150
        etypecls = self._cw.vreg['etypes'].etype_class(targettype)
7794
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1151
        etypecls.fetch_rqlst(self._cw.user, select, searchedvar,
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1152
                             ordermethod=ordermethod)
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1153
        # from now on, we need variable type resolving
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1154
        self._cw.vreg.solutions(self._cw, select, args)
7154
5e2f93b88d86 [entity vocabulary] refactor unrelated rql to allow usage of RQLRewriter to insert schema constraints. Closes #1561806
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7153
diff changeset
  1155
        # insert RQL expressions for schema constraints into the rql syntax tree
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1156
        if vocabconstraints:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1157
            # RQLConstraint is a subclass for RQLVocabularyConstraint, so they
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1158
            # will be included as well
7153
7df83a6d17c0 [entity vocabulary] fix unrelated rql generation to skip rql constraints that don't make sense
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7152
diff changeset
  1159
            cstrcls = RQLVocabularyConstraint
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1160
        else:
7153
7df83a6d17c0 [entity vocabulary] fix unrelated rql generation to skip rql constraints that don't make sense
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7152
diff changeset
  1161
            cstrcls = RQLConstraint
7973
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
  1162
        lt_infos = pruned_lt_info(self.e_schema, lt_infos or {})
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
  1163
        # if there are still lt_infos, use set to keep track of added eid
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
  1164
        # relations (adding twice the same eid relation is incorrect RQL)
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
  1165
        eidvars = set()
7153
7df83a6d17c0 [entity vocabulary] fix unrelated rql generation to skip rql constraints that don't make sense
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7152
diff changeset
  1166
        for cstr in rdef.constraints:
7154
5e2f93b88d86 [entity vocabulary] refactor unrelated rql to allow usage of RQLRewriter to insert schema constraints. Closes #1561806
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7153
diff changeset
  1167
            # consider constraint.mainvars to check if constraint apply
7794
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1168
            if isinstance(cstr, cstrcls) and searchedvar.name in cstr.mainvars:
7973
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
  1169
                if not self.has_eid():
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
  1170
                    if lt_infos:
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
  1171
                        # we can perhaps further restrict with linkto infos using
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
  1172
                        # a custom constraint built from cstr and lt_infos
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
  1173
                        cstr = build_cstr_with_linkto_infos(
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
  1174
                            cstr, args, searchedvar, evar, lt_infos, eidvars)
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
  1175
                        if cstr is None:
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
  1176
                            continue # could not build constraint -> discard
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
  1177
                    elif evar.name in cstr.mainvars:
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
  1178
                        continue
7154
5e2f93b88d86 [entity vocabulary] refactor unrelated rql to allow usage of RQLRewriter to insert schema constraints. Closes #1561806
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7153
diff changeset
  1179
                # compute a varmap suitable to RQLRewriter.rewrite argument
7794
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1180
                varmap = dict((v, v) for v in (searchedvar.name, evar.name)
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1181
                              if v in select.defined_vars and v in cstr.mainvars)
7154
5e2f93b88d86 [entity vocabulary] refactor unrelated rql to allow usage of RQLRewriter to insert schema constraints. Closes #1561806
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7153
diff changeset
  1182
                # rewrite constraint by constraint since we want a AND between
5e2f93b88d86 [entity vocabulary] refactor unrelated rql to allow usage of RQLRewriter to insert schema constraints. Closes #1561806
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7153
diff changeset
  1183
                # expressions.
9188
0677e03077fb [rqlrewrite] rewrite doesn't need a solutions argument, always use the Select'ones
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8992
diff changeset
  1184
                rewriter.rewrite(select, [(varmap, (cstr,))], args, existant)
7154
5e2f93b88d86 [entity vocabulary] refactor unrelated rql to allow usage of RQLRewriter to insert schema constraints. Closes #1561806
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7153
diff changeset
  1185
        # insert security RQL expressions granting the permission to 'add' the
5e2f93b88d86 [entity vocabulary] refactor unrelated rql to allow usage of RQLRewriter to insert schema constraints. Closes #1561806
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7153
diff changeset
  1186
        # relation into the rql syntax tree, if necessary
5e2f93b88d86 [entity vocabulary] refactor unrelated rql to allow usage of RQLRewriter to insert schema constraints. Closes #1561806
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7153
diff changeset
  1187
        rqlexprs = rdef.get_rqlexprs('add')
8472
444a8e25c940 [entity] fix unrelated_rql for creation form vocabulary for relation with specific permissions (closes #2423854)
Florent Cayré <florent.cayre@logilab.fr>
parents: 8307
diff changeset
  1188
        if not self.has_eid():
444a8e25c940 [entity] fix unrelated_rql for creation form vocabulary for relation with specific permissions (closes #2423854)
Florent Cayré <florent.cayre@logilab.fr>
parents: 8307
diff changeset
  1189
            rqlexprs = [rqlexpr for rqlexpr in rqlexprs
444a8e25c940 [entity] fix unrelated_rql for creation form vocabulary for relation with specific permissions (closes #2423854)
Florent Cayré <florent.cayre@logilab.fr>
parents: 8307
diff changeset
  1190
                        if searchedvar.name in rqlexpr.mainvars]
7154
5e2f93b88d86 [entity vocabulary] refactor unrelated rql to allow usage of RQLRewriter to insert schema constraints. Closes #1561806
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7153
diff changeset
  1191
        if rqlexprs and not rdef.has_perm(self._cw, 'add', **sec_check_args):
5e2f93b88d86 [entity vocabulary] refactor unrelated rql to allow usage of RQLRewriter to insert schema constraints. Closes #1561806
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7153
diff changeset
  1192
            # compute a varmap suitable to RQLRewriter.rewrite argument
7794
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1193
            varmap = dict((v, v) for v in (searchedvar.name, evar.name)
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1194
                          if v in select.defined_vars)
7154
5e2f93b88d86 [entity vocabulary] refactor unrelated rql to allow usage of RQLRewriter to insert schema constraints. Closes #1561806
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7153
diff changeset
  1195
            # rewrite all expressions at once since we want a OR between them.
9188
0677e03077fb [rqlrewrite] rewrite doesn't need a solutions argument, always use the Select'ones
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8992
diff changeset
  1196
            rewriter.rewrite(select, [(varmap, rqlexprs)], args, existant)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1197
        # ensure we have an order defined
7154
5e2f93b88d86 [entity vocabulary] refactor unrelated rql to allow usage of RQLRewriter to insert schema constraints. Closes #1561806
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7153
diff changeset
  1198
        if not select.orderby:
7794
aed065b97f12 refactor entity fetch_rql method to use a RQL syntax tree instead of RQL strings ; closes #1585650
Florent Cayré <florent.cayre@gmail.com>
parents: 7702
diff changeset
  1199
            select.add_sort_var(select.defined_vars[searchedvar.name])
7154
5e2f93b88d86 [entity vocabulary] refactor unrelated rql to allow usage of RQLRewriter to insert schema constraints. Closes #1561806
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7153
diff changeset
  1200
        # we're done, turn the rql syntax tree as a string
5e2f93b88d86 [entity vocabulary] refactor unrelated rql to allow usage of RQLRewriter to insert schema constraints. Closes #1561806
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7153
diff changeset
  1201
        rql = select.as_string()
3241
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
  1202
        return rql, args
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
  1203
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1204
    def unrelated(self, rtype, targettype, role='subject', limit=None,
7973
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
  1205
                  ordermethod=None, lt_infos={}): # XXX .cw_unrelated
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1206
        """return a result set of target type objects that may be related
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1207
        by a given relation, with self as subject or object
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1208
        """
3241
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
  1209
        try:
8735
5567a5117aeb [entity] ensure the .related(entities=False) parameter is honored all the way down (closes #2755994)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8705
diff changeset
  1210
            rql, args = self.cw_unrelated_rql(rtype, targettype, role, limit=limit,
5567a5117aeb [entity] ensure the .related(entities=False) parameter is honored all the way down (closes #2755994)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8705
diff changeset
  1211
                                              ordermethod=ordermethod, lt_infos=lt_infos)
3241
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
  1212
        except Unauthorized:
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
  1213
            return self._cw.empty_rset()
5174
78438ad513ca #759035: Automate addition of eid cachekey in RQL analysis
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
  1214
        return self._cw.execute(rql, args)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
  1215
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1216
    # relations cache handling #################################################
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
  1217
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1218
    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
  1219
        """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
  1220
        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
  1221
        """
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1222
        return self._cw_related_cache.get('%s_%s' % (rtype, role))
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
  1223
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1224
    def cw_set_relation_cache(self, rtype, role, rset):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1225
        """set cached values for the given relation"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1226
        if rset:
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1227
            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
  1228
            rschema = self._cw.vreg.schema.rschema(rtype)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1229
            if role == 'subject':
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
  1230
                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
  1231
                target = 'object'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1232
            else:
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
  1233
                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
  1234
                target = 'subject'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1235
            if rcard in '?1':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1236
                for rentity in related:
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1237
                    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
  1238
                        self.as_rset(), (self,))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1239
        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
  1240
            related = ()
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1241
        self._cw_related_cache['%s_%s' % (rtype, role)] = (rset, related)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
  1242
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1243
    def cw_clear_relation_cache(self, rtype=None, role=None):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1244
        """clear cached values for the given relation or the entire cache if
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1245
        no relation is given
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1246
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1247
        if rtype is None:
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1248
            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
  1249
            self._cw_adapters_cache = {}
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1250
        else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1251
            assert role
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1252
            self._cw_related_cache.pop('%s_%s' % (rtype, role), None)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
  1253
7293
97505b798975 [entity 3.13 api] rename clear_all_caches into cw_clear_all_cache
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7246
diff changeset
  1254
    def cw_clear_all_caches(self):
4408
899b426087ab [entity] small optimization: once an entity has been completed, don't redo it (for nothing)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4406
diff changeset
  1255
        """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
  1256
        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
  1257
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
  1258
        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
  1259
        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
  1260
        """
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
  1261
        # 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
  1262
        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
  1263
        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
  1264
        # 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
  1265
        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
  1266
        # 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
  1267
        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
  1268
            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
  1269
        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
  1270
            pass
4759
af2e6c377c71 cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4719
diff changeset
  1271
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1272
    # raw edition utilities ###################################################
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
  1273
8483
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
  1274
    def cw_set(self, **kwargs):
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
  1275
        """update this entity using given attributes / relation, working in the
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
  1276
        same fashion as :meth:`cw_instantiate`.
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
  1277
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
  1278
        Example (in a shell session):
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
  1279
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
  1280
        >>> c = rql('Any X WHERE X is Company').get_entity(0, 0)
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
  1281
        >>> p = rql('Any X WHERE X is Person').get_entity(0, 0)
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
  1282
        >>> c.set(name=u'Logilab')
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
  1283
        >>> p.set(firstname=u'John', lastname=u'Doe', works_for=c)
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
  1284
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
  1285
        You can also set relations where the entity has 'object' role by
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
  1286
        prefixing the relation name by 'reverse_'.  Also, relation values may be
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
  1287
        an entity or eid, a list of entities or eids, or None (meaning that all
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
  1288
        relations of the given type from or to this object should be deleted).
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
  1289
        """
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1290
        assert kwargs
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1291
        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
  1292
               "hasn't been saved yet"
8493
25da1e5c7c50 [entity/hooks] fix regression introduced by 4ba11607d84a
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8483
diff changeset
  1293
        rql, qargs, pendingrels, attrcache = self._cw_build_entity_query(kwargs)
8483
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
  1294
        if rql:
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
  1295
            rql = 'SET ' + rql
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
  1296
            qargs['x'] = self.eid
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
  1297
            if ' WHERE ' in rql:
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
  1298
                rql += ', X eid %(x)s'
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
  1299
            else:
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
  1300
                rql += ' WHERE X eid %(x)s'
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
  1301
            self._cw.execute(rql, qargs)
5115
2e43ef618d14 [repository] forbid usage of set_attributes() in before_add_entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5009
diff changeset
  1302
        # 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
  1303
        # 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
  1304
        # skip_security machinery
8493
25da1e5c7c50 [entity/hooks] fix regression introduced by 4ba11607d84a
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8483
diff changeset
  1305
        self._cw_update_attr_cache(attrcache)
25da1e5c7c50 [entity/hooks] fix regression introduced by 4ba11607d84a
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8483
diff changeset
  1306
        self._cw_handle_pending_relations(self.eid, pendingrels, self._cw.execute)
8483
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
  1307
        # XXX update relation cache
3671
c765adac7f5c new set_relations method on entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3665
diff changeset
  1308
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1309
    def cw_delete(self, **kwargs):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1310
        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
  1311
        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
  1312
                         {'x': self.eid}, **kwargs)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
  1313
6142
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1314
    # server side utilities ####################################################
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1315
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1316
    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
  1317
        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
  1318
            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
  1319
6142
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1320
    # deprecated stuff #########################################################
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1321
8980
c0b82dbcf6a3 [entity] improve deprecation messages
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 8735
diff changeset
  1322
    @deprecated('[3.16] use cw_set() instead of set_attributes()')
8483
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
  1323
    def set_attributes(self, **kwargs): # XXX cw_set_attributes
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
  1324
        self.cw_set(**kwargs)
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
  1325
8980
c0b82dbcf6a3 [entity] improve deprecation messages
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 8735
diff changeset
  1326
    @deprecated('[3.16] use cw_set() instead of set_relations()')
8483
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
  1327
    def set_relations(self, **kwargs): # XXX cw_set_relations
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
  1328
        """add relations to the given object. To set a relation where this entity
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
  1329
        is the object of the relation, use 'reverse_'<relation> as argument name.
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
  1330
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
  1331
        Values may be an entity or eid, a list of entities or eids, or None
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
  1332
        (meaning that all relations of the given type from or to this object
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
  1333
        should be deleted).
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
  1334
        """
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
  1335
        self.cw_set(**kwargs)
4ba11607d84a [entity api] unify set_attributes / set_relations into a cw_set method. Closes #2423719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8307
diff changeset
  1336
7293
97505b798975 [entity 3.13 api] rename clear_all_caches into cw_clear_all_cache
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7246
diff changeset
  1337
    @deprecated('[3.13] use entity.cw_clear_all_caches()')
97505b798975 [entity 3.13 api] rename clear_all_caches into cw_clear_all_cache
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7246
diff changeset
  1338
    def clear_all_caches(self):
97505b798975 [entity 3.13 api] rename clear_all_caches into cw_clear_all_cache
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7246
diff changeset
  1339
        return self.cw_clear_all_caches()
97505b798975 [entity 3.13 api] rename clear_all_caches into cw_clear_all_cache
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7246
diff changeset
  1340
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1341
    @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
  1342
    def get_value(self, name):
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1343
        return self.cw_attr_value(name)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
  1344
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1345
    @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
  1346
    def delete(self, **kwargs):
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1347
        return self.cw_delete(**kwargs)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1348
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1349
    @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
  1350
    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
  1351
        return self.cw_attr_metadata(attr, metadata)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
  1352
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1353
    @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
  1354
    def has_perm(self, action):
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1355
        return self.cw_has_perm(action)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1356
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1357
    @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
  1358
    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
  1359
        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
  1360
6812
a637f961665d typo in deprecation warning
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6807
diff changeset
  1361
    @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
  1362
    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
  1363
        self.cw_clear_relation_cache(rtype, role)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1364
5870
d3ec7c4bb373 restore bw compat on Entity.related_rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5797
diff changeset
  1365
    @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
  1366
    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
  1367
        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
  1368
6142
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1369
    @property
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1370
    @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
  1371
    def edited_attributes(self):
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1372
        return self.cw_edited
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1373
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1374
    @property
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1375
    @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
  1376
    def skip_security_attributes(self):
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1377
        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
  1378
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1379
    @property
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1380
    @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
  1381
    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
  1382
        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
  1383
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1384
    @property
6792
8834d9d91b66 [deprecation] fix bad warning on entity.querier_pending_relations
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6656
diff changeset
  1385
    @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
  1386
    def querier_pending_relations(self):
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1387
        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
  1388
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1389
    @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
  1390
    def __contains__(self, key):
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1391
        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
  1392
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1393
    @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
  1394
    def __iter__(self):
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1395
        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
  1396
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1397
    @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
  1398
    def __getitem__(self, key):
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1399
        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
  1400
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1401
    @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
  1402
    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
  1403
        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
  1404
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1405
    @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
  1406
    def clear(self):
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1407
        self.cw_attr_cache.clear()
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1408
        # XXX clear cw_edited ?
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1409
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1410
    @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
  1411
    def __setitem__(self, attr, value):
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1412
        """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
  1413
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1414
        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
  1415
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1416
            entity['generated_attr'] = generated_value
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1417
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1418
        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
  1419
        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
  1420
        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
  1421
        """
8793
3305b4a9df49 [entity] drop pre-3.7 api on session
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 8791
diff changeset
  1422
        try:
3305b4a9df49 [entity] drop pre-3.7 api on session
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 8791
diff changeset
  1423
            self.cw_edited[attr] = value
3305b4a9df49 [entity] drop pre-3.7 api on session
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 8791
diff changeset
  1424
        except AttributeError:
3305b4a9df49 [entity] drop pre-3.7 api on session
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 8791
diff changeset
  1425
            self.cw_attr_cache[attr] = value
6142
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1426
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1427
    @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
  1428
    def __delitem__(self, attr):
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1429
        """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
  1430
        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
  1431
        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
  1432
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1433
        .. sourcecode:: python
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1434
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1435
            edited = self.entity.cw_edited
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1436
            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
  1437
            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
  1438
                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
  1439
            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
  1440
                # 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
  1441
                del self.entity['load_left']
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1442
        """
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1443
        del self.cw_edited[attr]
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1444
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1445
    @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
  1446
    def setdefault(self, attr, default):
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1447
        """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
  1448
        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
  1449
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1450
    @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
  1451
    def pop(self, attr, *args):
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1452
        """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
  1453
        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
  1454
        """
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1455
        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
  1456
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1457
    @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
  1458
    def update(self, values):
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1459
        """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
  1460
        """
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1461
        self.cw_edited.update(values)
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1462
5870
d3ec7c4bb373 restore bw compat on Entity.related_rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5797
diff changeset
  1463
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1464
# attribute and relation descriptors ##########################################
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1465
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1466
class Attribute(object):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1467
    """descriptor that controls schema attribute access"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1468
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1469
    def __init__(self, attrname):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1470
        assert attrname != 'eid'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1471
        self._attrname = attrname
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1472
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1473
    def __get__(self, eobj, eclass):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1474
        if eobj is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1475
            return self
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1476
        return eobj.cw_attr_value(self._attrname)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1477
6499
c4123c741c66 [deprecation] enhanced messages
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6498
diff changeset
  1478
    @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
  1479
    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
  1480
        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
  1481
            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
  1482
        else:
0ad62d6b6f8e [bw compat] fix compat for entity.attr assigment
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6467
diff changeset
  1483
            eobj.cw_attr_cache[self._attrname] = value
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1484
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
  1485
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1486
class Relation(object):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1487
    """descriptor that controls schema relation access"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1488
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
  1489
    def __init__(self, rschema, role):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1490
        self._rtype = rschema.type
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
  1491
        self._role = role
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1492
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1493
    def __get__(self, eobj, eclass):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1494
        if eobj is None:
6419
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6317
diff changeset
  1495
            raise AttributeError('%s can only be accessed from instances'
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1496
                                 % self._rtype)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1497
        return eobj.related(self._rtype, self._role, entities=True)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
  1498
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1499
    def __set__(self, eobj, value):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1500
        raise NotImplementedError
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1501
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1502
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1503
from logging import getLogger
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1504
from cubicweb import set_log_methods
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1505
set_log_methods(Entity, getLogger('cubicweb.entity'))