entity.py
author Julien Cristau <julien.cristau@logilab.fr>
Fri, 20 Feb 2015 16:17:51 +0100
changeset 10317 b81adb5e32f9
parent 10041 504c4eacbfd8
child 10354 635cfac73d28
permissions -rw-r--r--
[web/views] add text/n3 rdf view Less shit than xml.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
9820
3ad221fe04aa [entity/rset] replace scary warnings about ambiguous rdefs by XXX in the code
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9774
diff changeset
     1
# copyright 2003-2014 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.decorators import cached
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
    26
from logilab.common.deprecation import deprecated
8190
2a3c1b787688 [vreg] move base registry implementation to logilab.common. Closes #1916014
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7995
diff changeset
    27
from logilab.common.registry import yes
8930
6a02be304486 remove unused import
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 8907
diff changeset
    28
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
    29
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    30
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
    31
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
    32
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
    33
                       Relation as RqlRelation)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    34
8748
f5027f8d2478 drop typed_eid() in favour of int() (closes #2742462)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 8735
diff changeset
    35
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
    36
from cubicweb.utils import support_args
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    37
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
    38
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
    39
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
    40
                             GeneratedConstraint)
3241
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
    41
from cubicweb.rqlrewrite import RQLRewriter
709
b21ee900c732 avoid dependency to common
sylvain.thenault@logilab.fr
parents: 707
diff changeset
    42
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
    43
from cubicweb.uilib import soup2xhtml
4023
eae23c40627a drop common subpackage
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3998
diff changeset
    44
from cubicweb.mttransforms import ENGINE
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    45
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    46
_marker = object()
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
def greater_card(rschema, subjtypes, objtypes, index):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    49
    for subjtype in subjtypes:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    50
        for objtype in objtypes:
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
    51
            card = rschema.rdef(subjtype, objtype).cardinality[index]
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    52
            if card in '+*':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    53
                return card
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    54
    return '1'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    55
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
    56
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
    57
    """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
    58
    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
    59
        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
    60
    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
    61
    # 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
    62
    # 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
    63
    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
    64
        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
    65
    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
    66
7973
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
    67
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
    68
    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
    69
             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
    70
            (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
    71
             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
    72
            )
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
    73
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
    74
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
    75
    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
    76
        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
    77
        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
    78
        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
    79
            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
    80
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
    81
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
    82
                                 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
    83
    """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
    84
    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
    85
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
    86
    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
    87
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
    88
      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
    89
          subject = 'CWUser'
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
    90
          object = 'Lab'
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
    91
          cardinality = '1*'
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
    92
          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
    93
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
    94
      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
    95
          subject = 'Lab'
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
    96
          object = 'CWGroup'
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
    97
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
    98
    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
    99
    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
   100
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   101
      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
   102
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   103
    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
   104
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   105
    """
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   106
    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
   107
    # 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
   108
    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
   109
        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
   110
        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
   111
            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
   112
            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
   113
                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
   114
                    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
   115
                else:
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   116
                    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
   117
                        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
   118
                        Constant)
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   119
                    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
   120
                    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
   121
                    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
   122
    # 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
   123
    # 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
   124
    # 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
   125
    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
   126
    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
   127
        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
   128
            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
   129
                return
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   130
    # 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
   131
    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
   132
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   133
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
   134
    pruned = {}
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   135
    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
   136
        # 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
   137
        # 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
   138
        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
   139
            continue
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   140
        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
   141
            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
   142
        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
   143
            continue
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
   144
        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
   145
    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
   146
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
   147
class Entity(AppObject):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   148
    """an entity instance has e_schema automagically set on
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   149
    the class and instances has access to their issuing cursor.
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   150
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   151
    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
   152
    class. Becare that among attributes, 'eid' is *NEITHER* stored in the
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   153
    dict containment (which acts as a cache for other attributes dynamically
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   154
    fetched)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   155
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   156
    :type e_schema: `cubicweb.schema.EntitySchema`
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   157
    :ivar e_schema: the entity's schema
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   158
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
   159
    :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
   160
    :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
   161
       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
   162
       be used ('eid' if none found)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   163
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
   164
    :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
   165
    :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
   166
       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
   167
       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
   168
       object cardinality are always skipped.
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   169
    """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   170
    __registry__ = 'etypes'
717
54b873918b48 kill id_registerer
sylvain.thenault@logilab.fr
parents: 714
diff changeset
   171
    __select__ = yes()
1264
fe2934a7df7f cleanup, avoid spurious warning
sylvain.thenault@logilab.fr
parents: 1177
diff changeset
   172
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   173
    # class attributes that must be set in class definition
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   174
    rest_attr = None
1138
22f634977c95 make pylint happy, fix some bugs on the way
sylvain.thenault@logilab.fr
parents: 1132
diff changeset
   175
    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
   176
    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
   177
    cw_skip_copy_for = [('in_state', 'subject')]
1264
fe2934a7df7f cleanup, avoid spurious warning
sylvain.thenault@logilab.fr
parents: 1177
diff changeset
   178
    # class attributes set automatically at registration time
fe2934a7df7f cleanup, avoid spurious warning
sylvain.thenault@logilab.fr
parents: 1177
diff changeset
   179
    e_schema = None
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   180
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   181
    @classmethod
2807
696ff03f9a58 __initialize__ needs the schema as argument
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2788
diff changeset
   182
    def __initialize__(cls, schema):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   183
        """initialize a specific entity class by adding descriptors to access
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   184
        entity type's attributes and relations
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   185
        """
3376
f5c69485381f [appobjects] use __regid__ instead of __id__, more explicit
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3369
diff changeset
   186
        etype = cls.__regid__
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   187
        assert etype != 'Any', etype
2807
696ff03f9a58 __initialize__ needs the schema as argument
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2788
diff changeset
   188
        cls.e_schema = eschema = schema.eschema(etype)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   189
        for rschema, _ in eschema.attribute_definitions():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   190
            if rschema.type == 'eid':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   191
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   192
            setattr(cls, rschema.type, Attribute(rschema.type))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   193
        mixins = []
2941
196493bd099c [entity] use role instead of x
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2931
diff changeset
   194
        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
   195
            if role == 'subject':
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   196
                attr = rschema.type
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   197
            else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   198
                attr = 'reverse_%s' % rschema.type
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   199
            setattr(cls, attr, Relation(rschema, role))
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   200
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   201
    fetch_attrs = ('modification_date',)
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   202
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   203
    @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
   204
    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
   205
        """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
   206
        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
   207
        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
   208
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
   209
        * `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
   210
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
   211
        * `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
   212
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
   213
        * `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
   214
          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
   215
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
   216
        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
   217
        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
   218
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
   219
        .. 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
   220
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
   221
          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
   222
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
   223
          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
   224
              __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
   225
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
              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
   227
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
              @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
   229
              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
   230
                  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
   231
                      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
   232
                      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
   233
                      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
   234
                      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
   235
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
        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
   237
        :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
   238
        """
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
        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
   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
    @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
   242
    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
   243
        """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
   244
        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
   245
        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
   246
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
        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
   248
        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
   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
        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
   251
        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
   252
        """
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   253
        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
   254
            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
   255
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   256
    @classmethod
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   257
    def fetch_rql(cls, user, restriction=None, fetchattrs=None, mainvar='X',
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   258
                  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
   259
        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
   260
                             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
   261
        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
   262
        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
   263
            # 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
   264
            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
   265
                 '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
   266
                 '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
   267
            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
   268
            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
   269
                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
   270
                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
   271
            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
   272
                rql += insert
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   273
        return rql
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   274
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   275
    @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
   276
    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
   277
                    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
   278
        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
   279
            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
   280
            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
   281
            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
   282
        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
   283
            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
   284
            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
   285
        # 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
   286
        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
   287
                                        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
   288
        if settype:
9359
31a1813d53f3 [entity/url publishing] fetch_rqlst should use 'is_instance_of' instead of 'is'
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9340
diff changeset
   289
            rel = select.add_type_restriction(mainvar, cls.__regid__)
31a1813d53f3 [entity/url publishing] fetch_rqlst should use 'is_instance_of' instead of 'is'
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9340
diff changeset
   290
            # should use 'is_instance_of' instead of 'is' so we retrieve
31a1813d53f3 [entity/url publishing] fetch_rqlst should use 'is_instance_of' instead of 'is'
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9340
diff changeset
   291
            # subclasses instances as well
31a1813d53f3 [entity/url publishing] fetch_rqlst should use 'is_instance_of' instead of 'is'
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9340
diff changeset
   292
            rel.r_type = 'is_instance_of'
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
   293
        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
   294
            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
   295
        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
   296
        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
   297
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
    @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
   299
    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
   300
        """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
   301
        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
   302
        "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
   303
        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
   304
        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
   305
        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
   306
        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
   307
        """
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
   308
        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
   309
            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
   310
            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
   311
                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
   312
            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
   313
            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
   314
                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
   315
                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
   316
                    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
   317
                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
   318
                    # 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
   319
                    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
   320
                    # ... 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
   321
                    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
   322
                    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
   323
                    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
   324
                    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
   325
                    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
   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
    @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
   328
    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
   329
                            user, ordermethod='fetch_order', visited=None):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   330
        eschema = cls.e_schema
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   331
        if visited is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   332
            visited = set((eschema.type,))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   333
        elif eschema.type in visited:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   334
            # avoid infinite recursion
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   335
            return
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   336
        else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   337
            visited.add(eschema.type)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   338
        _fetchattrs = []
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   339
        for attr in fetchattrs:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   340
            try:
3689
deb13e88e037 follow yams 0.25 api changes to improve performance
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3683
diff changeset
   341
                rschema = eschema.subjrels[attr]
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   342
            except KeyError:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   343
                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
   344
                            attr, cls.__regid__)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   345
                continue
9820
3ad221fe04aa [entity/rset] replace scary warnings about ambiguous rdefs by XXX in the code
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9774
diff changeset
   346
            # XXX takefirst=True to remove warning triggered by ambiguous inlined relations
3ad221fe04aa [entity/rset] replace scary warnings about ambiguous rdefs by XXX in the code
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9774
diff changeset
   347
            rdef = eschema.rdef(attr, takefirst=True)
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   348
            if not user.matching_groups(rdef.get_groups('read')):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   349
                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
   350
            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
   351
                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
   352
                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
   353
                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
   354
                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
   355
            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
   356
                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
   357
                            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
   358
                continue
3689
deb13e88e037 follow yams 0.25 api changes to improve performance
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3683
diff changeset
   359
            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
   360
                # 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
   361
                # (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
   362
                # 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
   363
                # 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
   364
                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
   365
                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
   366
                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
   367
                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
   368
                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
   369
                    # 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
   370
                    fetchattrs = vreg['etypes'].fetch_attrs(targettypes)
7803
02e141e41da2 some minor cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7798
diff changeset
   371
                    # ... 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
   372
                    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
   373
                                                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
   374
                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
   375
                    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
   376
                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
   377
                                             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
   378
            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
   379
                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
   380
                    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
   381
                    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
   382
                         % (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
   383
                         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
   384
                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
   385
                    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
   386
                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
   387
                    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
   388
                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
   389
                    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
   390
                         '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
   391
                         '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
   392
                    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
   393
                    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
   394
                        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
   395
                            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
   396
                        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
   397
                            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
   398
                                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
   399
                                          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
   400
                                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
   401
                            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
   402
                                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
   403
                                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
   404
                        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
   405
                            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
   406
                                                order=='ASC')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   407
1471
c889c3bcf5ec new parent_classes method (cached)
sylvain.thenault@logilab.fr
parents: 1435
diff changeset
   408
    @classmethod
c889c3bcf5ec new parent_classes method (cached)
sylvain.thenault@logilab.fr
parents: 1435
diff changeset
   409
    @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
   410
    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
   411
        """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
   412
        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
   413
        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
   414
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
   415
        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
   416
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
   417
        * 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
   418
        * 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
   419
        * '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
   420
        """
1840
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   421
        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
   422
        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
   423
            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
   424
            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
   425
        else:
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   426
            for rschema in cls.e_schema.subject_relations():
9978
8f4b15e5b300 [entities] cw_rest_attr_info() should only consider required attributes (closes #3766717)
Rémi Cardona <remi.cardona@logilab.fr>
parents: 9820
diff changeset
   427
                if (rschema.final
8f4b15e5b300 [entities] cw_rest_attr_info() should only consider required attributes (closes #3766717)
Rémi Cardona <remi.cardona@logilab.fr>
parents: 9820
diff changeset
   428
                    and rschema != 'eid'
8f4b15e5b300 [entities] cw_rest_attr_info() should only consider required attributes (closes #3766717)
Rémi Cardona <remi.cardona@logilab.fr>
parents: 9820
diff changeset
   429
                    and cls.e_schema.has_unique_values(rschema)
8f4b15e5b300 [entities] cw_rest_attr_info() should only consider required attributes (closes #3766717)
Rémi Cardona <remi.cardona@logilab.fr>
parents: 9820
diff changeset
   430
                    and cls.e_schema.rdef(rschema.type).cardinality[0] == '1'):
1840
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   431
                    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
   432
                    needcheck = False
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   433
                    break
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   434
        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
   435
            needcheck = False
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   436
        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
   437
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
   438
    @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
   439
    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
   440
        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
   441
        restrictions = set()
8493
25da1e5c7c50 [entity/hooks] fix regression introduced by 4ba11607d84a
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8483
diff changeset
   442
        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
   443
        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
   444
        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
   445
        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
   446
        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
   447
            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
   448
                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
   449
                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
   450
            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
   451
                role = 'subject'
7287
601ad29268ab [entity] improve error message
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 7213
diff changeset
   452
            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
   453
            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
   454
            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
   455
                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
   456
                    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
   457
                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
   458
                    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
   459
                else:
7213
7644e68c4e9f [entities] fix cw_instantiate typo
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7210
diff changeset
   460
                    # prepare IN clause
8493
25da1e5c7c50 [entity/hooks] fix regression introduced by 4ba11607d84a
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8483
diff changeset
   461
                    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
   462
                    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
   463
            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
   464
                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
   465
                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
   466
            elif value is None:
8493
25da1e5c7c50 [entity/hooks] fix regression introduced by 4ba11607d84a
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8483
diff changeset
   467
                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
   468
            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
   469
                rvar = attr.upper()
7213
7644e68c4e9f [entities] fix cw_instantiate typo
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7210
diff changeset
   470
                if role == 'object':
7644e68c4e9f [entities] fix cw_instantiate typo
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7210
diff changeset
   471
                    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
   472
                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
   473
                    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
   474
                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
   475
                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
   476
                    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
   477
                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
   478
                    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
   479
            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
   480
        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
   481
        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
   482
            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
   483
        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
   484
            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
   485
        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
   486
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
   487
    @classmethod
8493
25da1e5c7c50 [entity/hooks] fix regression introduced by 4ba11607d84a
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8483
diff changeset
   488
    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
   489
        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
   490
            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
   491
                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
   492
            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
   493
                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
   494
            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
   495
                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
   496
                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
   497
            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
   498
                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
   499
                    {'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
   500
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
   501
    @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
   502
    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
   503
        """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
   504
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
   505
        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
   506
8705
5b3e17a63fad Correct typo in example
Jérôme Roy <jerome.roy@logilab.fr>
parents: 8697
diff changeset
   507
        >>> companycls = vreg['etypes'].etype_class('Company')
5b3e17a63fad Correct typo in example
Jérôme Roy <jerome.roy@logilab.fr>
parents: 8697
diff changeset
   508
        >>> 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
   509
        >>> 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
   510
        >>> 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
   511
        ...                              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
   512
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
   513
        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
   514
        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
   515
        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
   516
        """
8493
25da1e5c7c50 [entity/hooks] fix regression introduced by 4ba11607d84a
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8483
diff changeset
   517
        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
   518
        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
   519
            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
   520
        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
   521
            rql = 'INSERT %s X' % (cls.__regid__)
10041
504c4eacbfd8 [entity] rather than crashing with an IndexError on entity creation, raise a meaningful exception
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10019
diff changeset
   522
        try:
504c4eacbfd8 [entity] rather than crashing with an IndexError on entity creation, raise a meaningful exception
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10019
diff changeset
   523
            created = execute(rql, qargs).get_entity(0, 0)
504c4eacbfd8 [entity] rather than crashing with an IndexError on entity creation, raise a meaningful exception
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10019
diff changeset
   524
        except IndexError:
504c4eacbfd8 [entity] rather than crashing with an IndexError on entity creation, raise a meaningful exception
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10019
diff changeset
   525
            raise Exception('could not create a %r with %r (%r)' %
504c4eacbfd8 [entity] rather than crashing with an IndexError on entity creation, raise a meaningful exception
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10019
diff changeset
   526
                            (cls.__regid__, rql, qargs))
8493
25da1e5c7c50 [entity/hooks] fix regression introduced by 4ba11607d84a
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8483
diff changeset
   527
        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
   528
        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
   529
        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
   530
1435
6cd6172718bb allow to instantiate an entity without rset
sylvain.thenault@logilab.fr
parents: 1363
diff changeset
   531
    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
   532
        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
   533
        self._cw_related_cache = {}
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   534
        if rset is not None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   535
            self.eid = rset[row][col]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   536
        else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   537
            self.eid = None
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   538
        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
   539
        self.cw_attr_cache = {}
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   540
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   541
    def __repr__(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   542
        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
   543
            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
   544
8892
80783605d270 [toward-py3k] rewrite __cmp__ (closes #2715115)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 8793
diff changeset
   545
    def __lt__(self, other):
80783605d270 [toward-py3k] rewrite __cmp__ (closes #2715115)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 8793
diff changeset
   546
        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
   547
80783605d270 [toward-py3k] rewrite __cmp__ (closes #2715115)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 8793
diff changeset
   548
    def __eq__(self, other):
9261
1dfe62a9da50 [entity] give a default reasonnable __eq__ and __hash__ to Entity
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9256
diff changeset
   549
        if isinstance(self.eid, (int, long)):
1dfe62a9da50 [entity] give a default reasonnable __eq__ and __hash__ to Entity
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9256
diff changeset
   550
            return self.eid == other.eid
1dfe62a9da50 [entity] give a default reasonnable __eq__ and __hash__ to Entity
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9256
diff changeset
   551
        return self is other
1dfe62a9da50 [entity] give a default reasonnable __eq__ and __hash__ to Entity
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9256
diff changeset
   552
1dfe62a9da50 [entity] give a default reasonnable __eq__ and __hash__ to Entity
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9256
diff changeset
   553
    def __hash__(self):
1dfe62a9da50 [entity] give a default reasonnable __eq__ and __hash__ to Entity
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9256
diff changeset
   554
        if isinstance(self.eid, (int, long)):
1dfe62a9da50 [entity] give a default reasonnable __eq__ and __hash__ to Entity
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9256
diff changeset
   555
            return self.eid
1dfe62a9da50 [entity] give a default reasonnable __eq__ and __hash__ to Entity
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9256
diff changeset
   556
        return super(Entity, self).__hash__()
6142
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
   557
8493
25da1e5c7c50 [entity/hooks] fix regression introduced by 4ba11607d84a
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8483
diff changeset
   558
    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
   559
        # if context is a repository session, don't consider dont-cache-attrs as
9774
b7b71be569cf deprecate get/set_shared_data API
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9712
diff changeset
   560
        # the instance already holds modified values and loosing them could
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
   561
        # introduce severe problems
9774
b7b71be569cf deprecate get/set_shared_data API
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9712
diff changeset
   562
        trdata = self._cw.transaction_data
b7b71be569cf deprecate get/set_shared_data API
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9712
diff changeset
   563
        uncached_attrs = trdata.get('%s.storage-special-process-attrs' % self.eid, set())
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 self._cw.is_request:
9774
b7b71be569cf deprecate get/set_shared_data API
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9712
diff changeset
   565
            uncached_attrs.update(trdata.get('%s.dont-cache-attrs' % self.eid, set()))
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
   566
        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
   567
            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
   568
            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
   569
        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
   570
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
   571
    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
   572
        """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
   573
        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
   574
        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
   575
4d24ac49f90d [entity] add a "repo_side" parameter to `_cw_dont_cache_attribute`
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 8660
diff changeset
   576
        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
   577
        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
   578
        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
   579
4d24ac49f90d [entity] add a "repo_side" parameter to `_cw_dont_cache_attribute`
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 8660
diff changeset
   580
        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
   581
        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
   582
        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
   583
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
        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
   585
        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
   586
        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
   587
        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
   588
        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
   589
        """
25da1e5c7c50 [entity/hooks] fix regression introduced by 4ba11607d84a
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8483
diff changeset
   590
        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
   591
        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
   592
            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
   593
            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
   594
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
   595
    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
   596
        """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
   597
        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
   598
        """
7876
df15d194a134 [views] implement json / jsonp export views (closes #1942658)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7828
diff changeset
   599
        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
   600
        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
   601
        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
   602
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   603
    def cw_adapt_to(self, interface):
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   604
        """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
   605
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   606
        return None if it can not be adapted.
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   607
        """
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   608
        try:
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   609
            cache = self._cw_adapters_cache
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   610
        except AttributeError:
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   611
            self._cw_adapters_cache = cache = {}
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   612
        try:
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   613
            return cache[interface]
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   614
        except KeyError:
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   615
            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
   616
                interface, self._cw, entity=self)
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   617
            cache[interface] = adapter
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
   618
            return adapter
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   619
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   620
    def has_eid(self): # XXX cw_has_eid
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   621
        """return True if the entity has an attributed eid (False
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   622
        meaning that the entity has to be created
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   623
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   624
        try:
8748
f5027f8d2478 drop typed_eid() in favour of int() (closes #2742462)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 8735
diff changeset
   625
            int(self.eid)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   626
            return True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   627
        except (ValueError, TypeError):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   628
            return False
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   629
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   630
    def cw_is_saved(self):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   631
        """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
   632
        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
   633
        '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
   634
        has an eid *and* is saved in its source.
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   635
        """
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   636
        return self.has_eid() and self._cw_is_saved
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   637
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   638
    @cached
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   639
    def cw_metainformation(self):
9469
032825bbacab [multi-sources-removal] Drop entities.source column
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9359
diff changeset
   640
        metas = self._cw.entity_metas(self.eid)
032825bbacab [multi-sources-removal] Drop entities.source column
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9359
diff changeset
   641
        metas['source'] = self._cw.source_defs()[metas['source']]
032825bbacab [multi-sources-removal] Drop entities.source column
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9359
diff changeset
   642
        return metas
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   643
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   644
    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
   645
        self.e_schema.check_perm(self._cw, action, eid=self.eid)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   646
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   647
    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
   648
        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
   649
6085
8a059eefac75 [entity] entity.view now support initargs as req.view
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5980
diff changeset
   650
    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
   651
        """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
   652
        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
   653
            initargs = kwargs
8a059eefac75 [entity] entity.view now support initargs as req.view
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5980
diff changeset
   654
        else:
8a059eefac75 [entity] entity.view now support initargs as req.view
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5980
diff changeset
   655
            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
   656
        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
   657
                                                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
   658
                                                **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
   659
        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
   660
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   661
    def absolute_url(self, *args, **kwargs): # XXX cw_url
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   662
        """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
   663
        # 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
   664
        # 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
   665
        if args:
af33833d7571 absolute_url / build_url refactoring to avoid potential name clash
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2058
diff changeset
   666
            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
   667
            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
   668
        else:
af33833d7571 absolute_url / build_url refactoring to avoid potential name clash
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2058
diff changeset
   669
            method = None
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   670
        # in linksearch mode, we don't want external urls else selecting
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   671
        # the object for use in the relation is tricky
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   672
        # 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
   673
        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
   674
        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
   675
               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
   676
            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
   677
            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
   678
                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
   679
            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
   680
                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
   681
                use_ext_id = True
1904
e23536d29231 minor refactoring of absolute_url()
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 1842
diff changeset
   682
        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
   683
            kwargs['_restpath'] = self.rest_path(use_ext_id)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   684
        else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   685
            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
   686
        return self._cw.build_url(method, **kwargs)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   687
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   688
    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
   689
        """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
   690
        mainattr, needcheck = self.cw_rest_attr_info()
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   691
        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
   692
        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
   693
        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
   694
        if mainattr != 'eid':
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   695
            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
   696
            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
   697
                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
   698
                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
   699
            elif needcheck:
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   700
                # 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
   701
                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
   702
                    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
   703
                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
   704
                    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
   705
                        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
   706
                    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
   707
                if nbresults != 1: # ambiguity?
e23536d29231 minor refactoring of absolute_url()
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 1842
diff changeset
   708
                    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
   709
                    path = None
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   710
        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
   711
            if use_ext_eid:
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   712
                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
   713
            else:
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   714
                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
   715
        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
   716
            # 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
   717
            # 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
   718
            return unicode(value)
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   719
        return '%s/%s' % (path, self._cw.url_quote(value))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   720
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   721
    def cw_attr_metadata(self, attr, metadata):
1101
0c067de38e46 unification of meta-attributes handling:
sylvain.thenault@logilab.fr
parents: 1098
diff changeset
   722
        """return a metadata for an attribute (None if unspecified)"""
0c067de38e46 unification of meta-attributes handling:
sylvain.thenault@logilab.fr
parents: 1098
diff changeset
   723
        value = getattr(self, '%s_%s' % (attr, metadata), None)
0c067de38e46 unification of meta-attributes handling:
sylvain.thenault@logilab.fr
parents: 1098
diff changeset
   724
        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
   725
            value = self._cw.vreg.property_value('ui.encoding')
1101
0c067de38e46 unification of meta-attributes handling:
sylvain.thenault@logilab.fr
parents: 1098
diff changeset
   726
        return value
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   727
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   728
    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
   729
                        format='text/html', displaytime=True): # XXX cw_printable_value
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   730
        """return a displayable value (i.e. unicode string) which may contains
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   731
        html tags
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   732
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   733
        attr = str(attr)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   734
        if value is _marker:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   735
            value = getattr(self, attr)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   736
        if isinstance(value, basestring):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   737
            value = value.strip()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   738
        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
   739
            return u''
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   740
        if attrtype is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   741
            attrtype = self.e_schema.destination(attr)
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   742
        props = self.e_schema.rdef(attr)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   743
        if attrtype == 'String':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   744
            # internalinalized *and* formatted string such as schema
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   745
            # description...
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   746
            if props.internationalizable:
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   747
                value = self._cw._(value)
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   748
            attrformat = self.cw_attr_metadata(attr, 'format')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   749
            if attrformat:
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   750
                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
   751
                                              self._cw.encoding)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   752
        elif attrtype == 'Bytes':
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   753
            attrformat = self.cw_attr_metadata(attr, 'format')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   754
            if attrformat:
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   755
                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
   756
                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
   757
                                              encoding)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   758
            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
   759
        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
   760
                                         displaytime=displaytime)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   761
        if format == 'text/html':
2312
af4d8f75c5db use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2125
diff changeset
   762
            value = xml_escape(value)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   763
        return value
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   764
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   765
    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
   766
                          _engine=ENGINE):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   767
        trdata = TransformData(data, format, encoding, appobject=self)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   768
        data = _engine.convert(trdata, target_format).decode()
9432
030745ac9873 [entities] unconditionnally sanitize the html output of printable_value
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9310
diff changeset
   769
        if target_format == 'text/html':
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   770
            data = soup2xhtml(data, self._cw.encoding)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   771
        return data
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   772
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   773
    # entity cloning ##########################################################
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   774
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   775
    def copy_relations(self, ceid): # XXX cw_copy_relations
3626
017869a514c3 [doc] updated docstrings
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 3552
diff changeset
   776
        """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
   777
        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
   778
        ceid designates the original entity).
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   779
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   780
        By default meta and composite relations are skipped.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   781
        Overrides this if you want another behaviour
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   782
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   783
        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
   784
        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
   785
        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
   786
        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
   787
            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
   788
            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
   789
                 '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
   790
                 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
   791
        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
   792
            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
   793
            skip_copy_for[role].add(rtype)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   794
        for rschema in self.e_schema.subject_relations():
9591
5b8bc486d0dc [entity] User-defined relation to skip for copy has precedence
Jérôme Roy <jerome.roy@logilab.fr>
parents: 9440
diff changeset
   795
            if rschema.type in skip_copy_for['subject']:
5b8bc486d0dc [entity] User-defined relation to skip for copy has precedence
Jérôme Roy <jerome.roy@logilab.fr>
parents: 9440
diff changeset
   796
                continue
3689
deb13e88e037 follow yams 0.25 api changes to improve performance
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3683
diff changeset
   797
            if rschema.final or rschema.meta:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   798
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   799
            # skip already defined relations
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   800
            if getattr(self, rschema.type):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   801
                continue
9820
3ad221fe04aa [entity/rset] replace scary warnings about ambiguous rdefs by XXX in the code
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9774
diff changeset
   802
            # XXX takefirst=True to remove warning triggered by ambiguous relations
3ad221fe04aa [entity/rset] replace scary warnings about ambiguous rdefs by XXX in the code
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9774
diff changeset
   803
            rdef = self.e_schema.rdef(rschema, takefirst=True)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   804
            # skip composite relation
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   805
            if rdef.composite:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   806
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   807
            # skip relation with card in ?1 else we either change the copied
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   808
            # object (inlined relation) or inserting some inconsistency
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   809
            if rdef.cardinality[1] in '?1':
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
            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
   812
                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
   813
            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
   814
            self.cw_clear_relation_cache(rschema.type, 'subject')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   815
        for rschema in self.e_schema.object_relations():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   816
            if rschema.meta:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   817
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   818
            # skip already defined relations
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   819
            if self.related(rschema.type, 'object'):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   820
                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
   821
            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
   822
                continue
9820
3ad221fe04aa [entity/rset] replace scary warnings about ambiguous rdefs by XXX in the code
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9774
diff changeset
   823
            # XXX takefirst=True to remove warning triggered by ambiguous relations
3ad221fe04aa [entity/rset] replace scary warnings about ambiguous rdefs by XXX in the code
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9774
diff changeset
   824
            rdef = self.e_schema.rdef(rschema, 'object', takefirst=True)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   825
            # skip composite relation
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   826
            if rdef.composite:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   827
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   828
            # skip relation with card in ?1 else we either change the copied
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   829
            # object (inlined relation) or inserting some inconsistency
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   830
            if rdef.cardinality[0] in '?1':
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   831
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   832
            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
   833
                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
   834
            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
   835
            self.cw_clear_relation_cache(rschema.type, 'object')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   836
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   837
    # data fetching methods ###################################################
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   838
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   839
    @cached
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   840
    def as_rset(self): # XXX .cw_as_rset
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   841
        """returns a resultset containing `self` information"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   842
        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
   843
                         {'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
   844
        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
   845
        return rset
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   846
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   847
    def _cw_to_complete_relations(self):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   848
        """by default complete final relations to when calling .complete()"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   849
        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
   850
            if rschema.final:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   851
                continue
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   852
            targets = rschema.objects(self.e_schema)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   853
            if rschema.inlined:
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   854
                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
   855
                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
   856
                       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
   857
                       for e in targets):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   858
                    yield rschema, 'subject'
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   859
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   860
    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
   861
        for rschema, attrschema in self.e_schema.attribute_definitions():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   862
            # skip binary data by default
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   863
            if skip_bytes and attrschema.type == 'Bytes':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   864
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   865
            attr = rschema.type
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   866
            if attr == 'eid':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   867
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   868
            # password retreival is blocked at the repository server level
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   869
            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
   870
            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
   871
                   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
   872
                self.cw_attr_cache[attr] = None
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   873
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   874
            yield attr
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   875
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
   876
    _cw_completed = False
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   877
    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
   878
        """complete this entity by adding missing attributes (i.e. query the
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   879
        repository to fill the entity)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   880
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   881
        :type skip_bytes: bool
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   882
        :param skip_bytes:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   883
          if true, attribute of type Bytes won't be considered
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   884
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   885
        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
   886
        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
   887
            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
   888
        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
   889
            self._cw_completed = True
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   890
        varmaker = rqlvar_maker()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   891
        V = varmaker.next()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   892
        rql = ['WHERE %s eid %%(x)s' % V]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   893
        selected = []
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   894
        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
   895
            # 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
   896
            if attr in self.cw_attr_cache:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   897
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   898
            # case where attribute must be completed, but is not yet in entity
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   899
            var = varmaker.next()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   900
            rql.append('%s %s %s' % (V, attr, var))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   901
            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
   902
        # +1 since this doesn't include the main variable
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   903
        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
   904
        # 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
   905
        # 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
   906
        if attributes is None and self.cw_metainformation()['source']['uri'] == 'system':
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   907
            # 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
   908
            for rschema, role in self._cw_to_complete_relations():
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   909
                rtype = rschema.type
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   910
                if self.cw_relation_cached(rtype, role):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   911
                    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
   912
                # 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
   913
                # * 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
   914
                # * 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
   915
                # * 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
   916
                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
   917
                assert role == 'subject'
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   918
                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
   919
                # 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
   920
                # 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
   921
                rql.append('%s %s %s?' % (V, rtype, var))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   922
                selected.append(((rtype, role), var))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   923
        if selected:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   924
            # select V, we need it as the left most selected variable
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   925
            # if some outer join are included to fetch inlined relations
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   926
            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
   927
                                    ','.join(rql))
6656
bea4ab297e67 [ms entity] proper error on external entity fetch error
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6499
diff changeset
   928
            try:
bea4ab297e67 [ms entity] proper error on external entity fetch error
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6499
diff changeset
   929
                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
   930
            except IndexError:
bea4ab297e67 [ms entity] proper error on external entity fetch error
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6499
diff changeset
   931
                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
   932
                                % self.eid)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   933
            # handle attributes
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   934
            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
   935
                self.cw_attr_cache[str(selected[i-1][0])] = rset[i]
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   936
            # handle relations
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   937
            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
   938
                rtype, role = selected[i-1][0]
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   939
                value = rset[i]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   940
                if value is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   941
                    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
   942
                    rrset.req = self._cw
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   943
                else:
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   944
                    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
   945
                self.cw_set_relation_cache(rtype, role, rrset)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   946
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   947
    def cw_attr_value(self, name):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   948
        """get value for the attribute relation <name>, query the repository
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   949
        to get the value if necessary.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   950
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   951
        :type name: str
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   952
        :param name: name of the attribute to get
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   953
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   954
        try:
6142
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
   955
            return self.cw_attr_cache[name]
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   956
        except KeyError:
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   957
            if not self.cw_is_saved():
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   958
                return None
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   959
            rql = "Any A WHERE X eid %%(x)s, X %s A" % name
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   960
            try:
5174
78438ad513ca #759035: Automate addition of eid cachekey in RQL analysis
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5144
diff changeset
   961
                rset = self._cw.execute(rql, {'x': self.eid})
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   962
            except Unauthorized:
6142
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
   963
                self.cw_attr_cache[name] = value = None
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   964
            else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   965
                assert rset.rowcount <= 1, (self, rql, rset.rowcount)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   966
                try:
6142
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
   967
                    self.cw_attr_cache[name] = value = rset.rows[0][0]
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   968
                except IndexError:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   969
                    # probably a multisource error
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   970
                    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
   971
                                  name, self.eid)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   972
                    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
   973
                        self.cw_attr_cache[name] = value = self._cw._('unaccessible')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   974
                    else:
6142
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
   975
                        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
   976
            return value
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   977
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
   978
    def related(self, rtype, role='subject', limit=None, entities=False, # XXX .cw_related
9293
723e2c586ea3 [entity] Entity.related(): add a targettypes argument (closes #2957313)
Aurelien Campeas
parents: 9283
diff changeset
   979
                safe=False, targettypes=None):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   980
        """returns a resultset of related entities
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   981
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
   982
        :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
   983
          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
   984
        :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
   985
          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
   986
        :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
   987
          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
   988
        :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
   989
          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
   990
        :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
   991
          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
   992
          :exc:`Unauthorized`, else (the default), the exception is propagated
9293
723e2c586ea3 [entity] Entity.related(): add a targettypes argument (closes #2957313)
Aurelien Campeas
parents: 9283
diff changeset
   993
        :param targettypes:
723e2c586ea3 [entity] Entity.related(): add a targettypes argument (closes #2957313)
Aurelien Campeas
parents: 9283
diff changeset
   994
          a tuple of target entity types to restrict the query
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   995
        """
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
   996
        rtype = str(rtype)
9293
723e2c586ea3 [entity] Entity.related(): add a targettypes argument (closes #2957313)
Aurelien Campeas
parents: 9283
diff changeset
   997
        # Caching restricted/limited results is best avoided.
723e2c586ea3 [entity] Entity.related(): add a targettypes argument (closes #2957313)
Aurelien Campeas
parents: 9283
diff changeset
   998
        cacheable = limit is None and targettypes is None
723e2c586ea3 [entity] Entity.related(): add a targettypes argument (closes #2957313)
Aurelien Campeas
parents: 9283
diff changeset
   999
        if cacheable:
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
  1000
            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
  1001
            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
  1002
                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
  1003
        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
  1004
            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
  1005
                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
  1006
            return self._cw.empty_rset()
9293
723e2c586ea3 [entity] Entity.related(): add a targettypes argument (closes #2957313)
Aurelien Campeas
parents: 9283
diff changeset
  1007
        rql = self.cw_related_rql(rtype, role, limit=limit, targettypes=targettypes)
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
  1008
        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
  1009
            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
  1010
        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
  1011
            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
  1012
                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
  1013
            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
  1014
        if entities:
9293
723e2c586ea3 [entity] Entity.related(): add a targettypes argument (closes #2957313)
Aurelien Campeas
parents: 9283
diff changeset
  1015
            if cacheable:
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
  1016
                self.cw_set_relation_cache(rtype, role, rset)
9293
723e2c586ea3 [entity] Entity.related(): add a targettypes argument (closes #2957313)
Aurelien Campeas
parents: 9283
diff changeset
  1017
                return self.related(rtype, role, entities=entities)
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
            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
  1019
        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
  1020
            return rset
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1021
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
  1022
    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
  1023
        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
  1024
        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
  1025
        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
  1026
        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
  1027
        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
  1028
        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
  1029
            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
  1030
        select.add_eid_restriction(evar, 'x', 'Substitute')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1031
        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
  1032
            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
  1033
            select.add_restriction(rel)
3130
2486163c4630 allow to specify targettypes in related_rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3047
diff changeset
  1034
            if targettypes is None:
2486163c4630 allow to specify targettypes in related_rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3047
diff changeset
  1035
                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
  1036
            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
  1037
                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
  1038
                                                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
  1039
            gcard = greater_card(rschema, (self.e_schema,), targettypes, 0)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
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
            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
  1042
            select.add_restriction(rel)
3130
2486163c4630 allow to specify targettypes in related_rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3047
diff changeset
  1043
            if targettypes is None:
2486163c4630 allow to specify targettypes in related_rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3047
diff changeset
  1044
                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
  1045
            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
  1046
                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
  1047
                                                '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
  1048
            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
  1049
        etypecls = vreg['etypes'].etype_class(targettypes[0])
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1050
        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
  1051
            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
  1052
            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
  1053
                                         targettypes, vreg.schema)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1054
        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
  1055
            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
  1056
        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
  1057
                             settype=False)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1058
        # optimisation: remove ORDERBY if cardinality is 1 or ? (though
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1059
        # 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
  1060
        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
  1061
            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
  1062
        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
  1063
            # 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
  1064
            # 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
  1065
            # 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
  1066
            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
  1067
                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
  1068
                    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
  1069
                    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
  1070
                    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
  1071
                    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
  1072
                    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
  1073
            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
  1074
                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
  1075
                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
  1076
                                    (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
  1077
                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
  1078
                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
  1079
        return select.as_string()
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
  1080
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1081
    # generic vocabulary methods ##############################################
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1082
9712
6c6cd8c4b256 [entity] add a new `cw_linkable_rql` method
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9635
diff changeset
  1083
    def cw_linkable_rql(self, rtype, targettype, role, ordermethod=None,
6c6cd8c4b256 [entity] add a new `cw_linkable_rql` method
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9635
diff changeset
  1084
                        vocabconstraints=True, lt_infos={}, limit=None):
6c6cd8c4b256 [entity] add a new `cw_linkable_rql` method
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9635
diff changeset
  1085
        """build a rql to fetch targettype entities either related or unrelated
6c6cd8c4b256 [entity] add a new `cw_linkable_rql` method
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9635
diff changeset
  1086
        to this entity using (rtype, role) relation.
6c6cd8c4b256 [entity] add a new `cw_linkable_rql` method
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9635
diff changeset
  1087
6c6cd8c4b256 [entity] add a new `cw_linkable_rql` method
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9635
diff changeset
  1088
        Consider relation permissions so that returned entities may be actually
6c6cd8c4b256 [entity] add a new `cw_linkable_rql` method
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9635
diff changeset
  1089
        linked by `rtype`.
6c6cd8c4b256 [entity] add a new `cw_linkable_rql` method
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9635
diff changeset
  1090
6c6cd8c4b256 [entity] add a new `cw_linkable_rql` method
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9635
diff changeset
  1091
        `lt_infos` are supplementary informations, usually coming from __linkto
6c6cd8c4b256 [entity] add a new `cw_linkable_rql` method
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9635
diff changeset
  1092
        parameter, that can help further restricting the results in case current
6c6cd8c4b256 [entity] add a new `cw_linkable_rql` method
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9635
diff changeset
  1093
        entity is not yet created. It is a dict describing entities the current
6c6cd8c4b256 [entity] add a new `cw_linkable_rql` method
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9635
diff changeset
  1094
        entity will be linked to, which keys are (rtype, role) tuples and values
6c6cd8c4b256 [entity] add a new `cw_linkable_rql` method
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9635
diff changeset
  1095
        are a list of eids.
6c6cd8c4b256 [entity] add a new `cw_linkable_rql` method
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9635
diff changeset
  1096
        """
6c6cd8c4b256 [entity] add a new `cw_linkable_rql` method
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9635
diff changeset
  1097
        return self._cw_compute_linkable_rql(rtype, targettype, role, ordermethod=None,
6c6cd8c4b256 [entity] add a new `cw_linkable_rql` method
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9635
diff changeset
  1098
                                             vocabconstraints=vocabconstraints,
6c6cd8c4b256 [entity] add a new `cw_linkable_rql` method
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9635
diff changeset
  1099
                                             lt_infos=lt_infos, limit=limit,
6c6cd8c4b256 [entity] add a new `cw_linkable_rql` method
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9635
diff changeset
  1100
                                             unrelated_only=False)
6c6cd8c4b256 [entity] add a new `cw_linkable_rql` method
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9635
diff changeset
  1101
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1102
    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
  1103
                         vocabconstraints=True, lt_infos={}, limit=None):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1104
        """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
  1105
        using (rtype, role) relation.
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
  1106
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
  1107
        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
  1108
        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
  1109
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
  1110
        `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
  1111
        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
  1112
        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
  1113
        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
  1114
        are a list of eids.
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1115
        """
9712
6c6cd8c4b256 [entity] add a new `cw_linkable_rql` method
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9635
diff changeset
  1116
        return self._cw_compute_linkable_rql(rtype, targettype, role, ordermethod=None,
6c6cd8c4b256 [entity] add a new `cw_linkable_rql` method
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9635
diff changeset
  1117
                                             vocabconstraints=vocabconstraints,
6c6cd8c4b256 [entity] add a new `cw_linkable_rql` method
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9635
diff changeset
  1118
                                             lt_infos=lt_infos, limit=limit,
6c6cd8c4b256 [entity] add a new `cw_linkable_rql` method
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9635
diff changeset
  1119
                                             unrelated_only=True)
6c6cd8c4b256 [entity] add a new `cw_linkable_rql` method
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9635
diff changeset
  1120
6c6cd8c4b256 [entity] add a new `cw_linkable_rql` method
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9635
diff changeset
  1121
    def _cw_compute_linkable_rql(self, rtype, targettype, role, ordermethod=None,
6c6cd8c4b256 [entity] add a new `cw_linkable_rql` method
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9635
diff changeset
  1122
                                 vocabconstraints=True, lt_infos={}, limit=None,
6c6cd8c4b256 [entity] add a new `cw_linkable_rql` method
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9635
diff changeset
  1123
                                 unrelated_only=False):
6c6cd8c4b256 [entity] add a new `cw_linkable_rql` method
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9635
diff changeset
  1124
        """build a rql to fetch `targettype` entities that may be related to
6c6cd8c4b256 [entity] add a new `cw_linkable_rql` method
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9635
diff changeset
  1125
        this entity using the (rtype, role) relation.
6c6cd8c4b256 [entity] add a new `cw_linkable_rql` method
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9635
diff changeset
  1126
6c6cd8c4b256 [entity] add a new `cw_linkable_rql` method
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9635
diff changeset
  1127
        By default (unrelated_only=False), this includes the already linked
6c6cd8c4b256 [entity] add a new `cw_linkable_rql` method
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9635
diff changeset
  1128
        entities as well as the unrelated ones. If `unrelated_only` is True, the
6c6cd8c4b256 [entity] add a new `cw_linkable_rql` method
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9635
diff changeset
  1129
        rql filters out the already related entities.
6c6cd8c4b256 [entity] add a new `cw_linkable_rql` method
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9635
diff changeset
  1130
        """
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1131
        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
  1132
        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
  1133
        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
  1134
        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
  1135
        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
  1136
        # 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
  1137
        # 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
  1138
        # * 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
  1139
        # * variable for searched entities (`searchvedvar`)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1140
        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
  1141
            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
  1142
            searchedvar = objvar = select.get_variable('O')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1143
        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
  1144
            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
  1145
            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
  1146
        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
  1147
        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
  1148
            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
  1149
        # 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
  1150
        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
  1151
            # 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
  1152
            # 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
  1153
            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
  1154
            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
  1155
                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
  1156
            else:
7973
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7964
diff changeset
  1157
                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
  1158
            select.add_restriction(Not(rel))
9712
6c6cd8c4b256 [entity] add a new `cw_linkable_rql` method
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9635
diff changeset
  1159
        elif self.has_eid() and unrelated_only:
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
  1160
            # 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
  1161
            # 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
  1162
            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
  1163
            select.add_restriction(Not(rel))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1164
        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
  1165
            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
  1166
            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
  1167
            args = {'x': self.eid}
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
  1168
            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
  1169
                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
  1170
            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
  1171
                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
  1172
            existant = None # instead of 'SO', improve perfs
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1173
        else:
3241
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
  1174
            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
  1175
            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
  1176
            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
  1177
            # 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
  1178
            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
  1179
        # 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
  1180
        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
  1181
        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
  1182
                             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
  1183
        # 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
  1184
        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
  1185
        # insert RQL expressions for schema constraints into the rql syntax tree
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1186
        if vocabconstraints:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1187
            # RQLConstraint is a subclass for RQLVocabularyConstraint, so they
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1188
            # 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
  1189
            cstrcls = RQLVocabularyConstraint
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1190
        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
  1191
            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
  1192
        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
  1193
        # 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
  1194
        # 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
  1195
        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
  1196
        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
  1197
            # 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
  1198
            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
  1199
                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
  1200
                    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
  1201
                        # 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
  1202
                        # 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
  1203
                        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
  1204
                            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
  1205
                        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
  1206
                            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
  1207
                    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
  1208
                        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
  1209
                # 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
  1210
                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
  1211
                              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
  1212
                # 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
  1213
                # 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
  1214
                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
  1215
        # 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
  1216
        # 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
  1217
        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
  1218
        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
  1219
            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
  1220
                        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
  1221
        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
  1222
            # 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
  1223
            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
  1224
                          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
  1225
            # 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
  1226
            rewriter.rewrite(select, [(varmap, rqlexprs)], args, existant)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1227
        # 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
  1228
        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
  1229
            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
  1230
        # 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
  1231
        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
  1232
        return rql, args
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
  1233
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1234
    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
  1235
                  ordermethod=None, lt_infos={}): # XXX .cw_unrelated
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1236
        """return a result set of target type objects that may be related
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1237
        by a given relation, with self as subject or object
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1238
        """
3241
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
  1239
        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
  1240
            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
  1241
                                              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
  1242
        except Unauthorized:
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
  1243
            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
  1244
        return self._cw.execute(rql, args)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
  1245
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1246
    # relations cache handling #################################################
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
  1247
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1248
    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
  1249
        """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
  1250
        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
  1251
        """
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1252
        return self._cw_related_cache.get('%s_%s' % (rtype, role))
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
  1253
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1254
    def cw_set_relation_cache(self, rtype, role, rset):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1255
        """set cached values for the given relation"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1256
        if rset:
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1257
            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
  1258
            rschema = self._cw.vreg.schema.rschema(rtype)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1259
            if role == 'subject':
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
  1260
                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
  1261
                target = 'object'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1262
            else:
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
  1263
                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
  1264
                target = 'subject'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1265
            if rcard in '?1':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1266
                for rentity in related:
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1267
                    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
  1268
                        self.as_rset(), (self,))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1269
        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
  1270
            related = ()
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1271
        self._cw_related_cache['%s_%s' % (rtype, role)] = (rset, related)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
  1272
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1273
    def cw_clear_relation_cache(self, rtype=None, role=None):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1274
        """clear cached values for the given relation or the entire cache if
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1275
        no relation is given
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1276
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1277
        if rtype is None:
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1278
            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
  1279
            self._cw_adapters_cache = {}
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1280
        else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1281
            assert role
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1282
            self._cw_related_cache.pop('%s_%s' % (rtype, role), None)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
  1283
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
  1284
    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
  1285
        """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
  1286
        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
  1287
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
  1288
        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
  1289
        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
  1290
        """
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
  1291
        # 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
  1292
        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
  1293
        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
  1294
        # 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
  1295
        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
  1296
        # 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
  1297
        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
  1298
            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
  1299
        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
  1300
            pass
4759
af2e6c377c71 cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4719
diff changeset
  1301
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1302
    # raw edition utilities ###################################################
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
  1303
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
  1304
    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
  1305
        """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
  1306
        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
  1307
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
  1308
        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
  1309
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
  1310
        >>> 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
  1311
        >>> p = rql('Any X WHERE X is Person').get_entity(0, 0)
9310
80c58c35145f Fix example in cw_set method
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 9277
diff changeset
  1312
        >>> c.cw_set(name=u'Logilab')
80c58c35145f Fix example in cw_set method
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 9277
diff changeset
  1313
        >>> p.cw_set(firstname=u'John', lastname=u'Doe', works_for=c)
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
  1314
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
  1315
        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
  1316
        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
  1317
        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
  1318
        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
  1319
        """
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1320
        assert kwargs
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1321
        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
  1322
               "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
  1323
        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
  1324
        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
  1325
            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
  1326
            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
  1327
            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
  1328
                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
  1329
            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
  1330
                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
  1331
            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
  1332
        # 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
  1333
        # 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
  1334
        # skip_security machinery
8493
25da1e5c7c50 [entity/hooks] fix regression introduced by 4ba11607d84a
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8483
diff changeset
  1335
        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
  1336
        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
  1337
        # XXX update relation cache
3671
c765adac7f5c new set_relations method on entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3665
diff changeset
  1338
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1339
    def cw_delete(self, **kwargs):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1340
        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
  1341
        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
  1342
                         {'x': self.eid}, **kwargs)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
  1343
6142
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1344
    # server side utilities ####################################################
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1345
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1346
    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
  1347
        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
  1348
            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
  1349
6142
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6124
diff changeset
  1350
    # deprecated stuff #########################################################
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1351
8980
c0b82dbcf6a3 [entity] improve deprecation messages
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 8735
diff changeset
  1352
    @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
  1353
    def set_attributes(self, **kwargs): # XXX cw_set_attributes
9277
c964d8cf6efc [entity] do not raise an AssertionError if the kwargs given to set_relations/attributes is empty
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9188
diff changeset
  1354
        if kwargs:
c964d8cf6efc [entity] do not raise an AssertionError if the kwargs given to set_relations/attributes is empty
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9188
diff changeset
  1355
            self.cw_set(**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
  1356
8980
c0b82dbcf6a3 [entity] improve deprecation messages
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 8735
diff changeset
  1357
    @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
  1358
    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
  1359
        """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
  1360
        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
  1361
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
  1362
        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
  1363
        (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
  1364
        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
  1365
        """
9277
c964d8cf6efc [entity] do not raise an AssertionError if the kwargs given to set_relations/attributes is empty
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9188
diff changeset
  1366
        if kwargs:
c964d8cf6efc [entity] do not raise an AssertionError if the kwargs given to set_relations/attributes is empty
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9188
diff changeset
  1367
            self.cw_set(**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
  1368
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
  1369
    @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
  1370
    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
  1371
        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
  1372
5870
d3ec7c4bb373 restore bw compat on Entity.related_rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5797
diff changeset
  1373
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1374
# attribute and relation descriptors ##########################################
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1375
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1376
class Attribute(object):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1377
    """descriptor that controls schema attribute access"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1378
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1379
    def __init__(self, attrname):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1380
        assert attrname != 'eid'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1381
        self._attrname = attrname
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1382
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1383
    def __get__(self, eobj, eclass):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1384
        if eobj is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1385
            return self
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1386
        return eobj.cw_attr_value(self._attrname)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1387
6499
c4123c741c66 [deprecation] enhanced messages
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6498
diff changeset
  1388
    @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
  1389
    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
  1390
        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
  1391
            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
  1392
        else:
0ad62d6b6f8e [bw compat] fix compat for entity.attr assigment
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6467
diff changeset
  1393
            eobj.cw_attr_cache[self._attrname] = value
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1394
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
  1395
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1396
class Relation(object):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1397
    """descriptor that controls schema relation access"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1398
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
  1399
    def __init__(self, rschema, role):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1400
        self._rtype = rschema.type
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5522
diff changeset
  1401
        self._role = role
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1402
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1403
    def __get__(self, eobj, eclass):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1404
        if eobj is None:
6419
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6317
diff changeset
  1405
            raise AttributeError('%s can only be accessed from instances'
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1406
                                 % self._rtype)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1407
        return eobj.related(self._rtype, self._role, entities=True)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
  1408
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1409
    def __set__(self, eobj, value):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1410
        raise NotImplementedError
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1411
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1412
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1413
from logging import getLogger
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1414
from cubicweb import set_log_methods
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1415
set_log_methods(Entity, getLogger('cubicweb.entity'))