entity.py
author Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
Fri, 19 Mar 2010 19:21:31 +0100
changeset 4964 d9e8af8a7a42
parent 4913 083b4d454192
child 4965 04543ed0bbdc
permissions -rw-r--r--
[source] implement storages right in the source rather than in hooks The problem is that Storage objects will most probably change entity's dictionary so that values are correctly set before the source's corresponding method (e.g. entity_added()) is called. For instance, the BFSFileStorage will change the original binary data and replace it with the destination file path in order to store the file path in the database. This change must be local to the source in order not to impact other hooks or attribute access during the transaction, the whole idea being that the same application code should work exactly the same whether or not a BFSStorage is used or not.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     1
"""Base class for entity objects manipulated in clients
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     2
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     3
:organization: Logilab
4212
ab6573088b4a update copyright: welcome 2010
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3961
diff changeset
     4
:copyright: 2001-2010 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2.
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     5
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
1977
606923dff11b big bunch of copyright / docstring update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1904
diff changeset
     6
:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     7
"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     8
__docformat__ = "restructuredtext en"
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     9
1154
9b23a6836c32 support for old __rtags__
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
    10
from warnings import warn
9b23a6836c32 support for old __rtags__
sylvain.thenault@logilab.fr
parents: 1138
diff changeset
    11
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    12
from logilab.common import interface
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    13
from logilab.common.compat import all
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    14
from logilab.common.decorators import cached
2312
af4d8f75c5db use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2125
diff changeset
    15
from logilab.mtconverter import TransformData, TransformError, xml_escape
631
99f5852f8604 major selector refactoring (mostly to avoid looking for select parameters on the target class), start accept / interface unification)
sylvain.thenault@logilab.fr
parents: 479
diff changeset
    16
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    17
from rql.utils import rqlvar_maker
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    18
3664
af7ca3597b8d use typed_eid
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3626
diff changeset
    19
from cubicweb import Unauthorized, typed_eid
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    20
from cubicweb.rset import ResultSet
692
800592b8d39b replace deprecated cubicweb.common.selectors by its new module path (cubicweb.selectors)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 631
diff changeset
    21
from cubicweb.selectors import yes
2656
a93ae0f6c0ad R [base classes] only AppObject remaning, no more AppRsetObject
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
    22
from cubicweb.appobject import AppObject
4835
13b0b96d7982 [repo] enhanced security handling: deprecates unsafe_execute, in favor of explicit read/write security control using the `enabled_security` context manager. Also code executed on the repository side is now unsafe by default.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4831
diff changeset
    23
from cubicweb.req import _check_cw_unsafe
2827
d1a89d165045 remove 3.2 bw compat code
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2824
diff changeset
    24
from cubicweb.schema import RQLVocabularyConstraint, RQLConstraint
3241
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
    25
from cubicweb.rqlrewrite import RQLRewriter
709
b21ee900c732 avoid dependency to common
sylvain.thenault@logilab.fr
parents: 707
diff changeset
    26
4023
eae23c40627a drop common subpackage
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3998
diff changeset
    27
from cubicweb.uilib import printable_value, soup2xhtml
eae23c40627a drop common subpackage
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3998
diff changeset
    28
from cubicweb.mixins import MI_REL_TRIGGERS
eae23c40627a drop common subpackage
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3998
diff changeset
    29
from cubicweb.mttransforms import ENGINE
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    30
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    31
_marker = object()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    32
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    33
def greater_card(rschema, subjtypes, objtypes, index):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    34
    for subjtype in subjtypes:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    35
        for objtype in objtypes:
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
    36
            card = rschema.rdef(subjtype, objtype).cardinality[index]
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    37
            if card in '+*':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    38
                return card
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    39
    return '1'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    40
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    41
2656
a93ae0f6c0ad R [base classes] only AppObject remaning, no more AppRsetObject
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
    42
class Entity(AppObject, dict):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    43
    """an entity instance has e_schema automagically set on
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    44
    the class and instances has access to their issuing cursor.
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
    45
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    46
    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
    47
    class. Becare that among attributes, 'eid' is *NEITHER* stored in the
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    48
    dict containment (which acts as a cache for other attributes dynamically
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    49
    fetched)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    50
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    51
    :type e_schema: `cubicweb.schema.EntitySchema`
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    52
    :ivar e_schema: the entity's schema
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    53
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    54
    :type rest_var: str
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    55
    :cvar rest_var: indicates which attribute should be used to build REST urls
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    56
                    If None is specified, the first non-meta attribute will
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    57
                    be used
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
    58
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    59
    :type skip_copy_for: list
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    60
    :cvar skip_copy_for: a list of relations that should be skipped when copying
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    61
                         this kind of entity. Note that some relations such
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    62
                         as composite relations or relations that have '?1' as object
3626
017869a514c3 [doc] updated docstrings
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 3552
diff changeset
    63
                         cardinality are always skipped. 
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    64
    """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    65
    __registry__ = 'etypes'
717
54b873918b48 kill id_registerer
sylvain.thenault@logilab.fr
parents: 714
diff changeset
    66
    __select__ = yes()
1264
fe2934a7df7f cleanup, avoid spurious warning
sylvain.thenault@logilab.fr
parents: 1177
diff changeset
    67
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
    68
    # class attributes that must be set in class definition
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    69
    rest_attr = None
1138
22f634977c95 make pylint happy, fix some bugs on the way
sylvain.thenault@logilab.fr
parents: 1132
diff changeset
    70
    fetch_attrs = None
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2877
diff changeset
    71
    skip_copy_for = ('in_state',)
1264
fe2934a7df7f cleanup, avoid spurious warning
sylvain.thenault@logilab.fr
parents: 1177
diff changeset
    72
    # class attributes set automatically at registration time
fe2934a7df7f cleanup, avoid spurious warning
sylvain.thenault@logilab.fr
parents: 1177
diff changeset
    73
    e_schema = None
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
    74
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    75
    @classmethod
2807
696ff03f9a58 __initialize__ needs the schema as argument
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2788
diff changeset
    76
    def __initialize__(cls, schema):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    77
        """initialize a specific entity class by adding descriptors to access
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    78
        entity type's attributes and relations
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    79
        """
3376
f5c69485381f [appobjects] use __regid__ instead of __id__, more explicit
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3369
diff changeset
    80
        etype = cls.__regid__
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    81
        assert etype != 'Any', etype
2807
696ff03f9a58 __initialize__ needs the schema as argument
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2788
diff changeset
    82
        cls.e_schema = eschema = schema.eschema(etype)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    83
        for rschema, _ in eschema.attribute_definitions():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    84
            if rschema.type == 'eid':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    85
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    86
            setattr(cls, rschema.type, Attribute(rschema.type))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    87
        mixins = []
2941
196493bd099c [entity] use role instead of x
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2931
diff changeset
    88
        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
    89
            if (rschema, role) in MI_REL_TRIGGERS:
196493bd099c [entity] use role instead of x
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2931
diff changeset
    90
                mixin = MI_REL_TRIGGERS[(rschema, role)]
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    91
                if not (issubclass(cls, mixin) or mixin in mixins): # already mixed ?
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    92
                    mixins.append(mixin)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    93
                for iface in getattr(mixin, '__implements__', ()):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    94
                    if not interface.implements(cls, iface):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    95
                        interface.extend(cls, iface)
2941
196493bd099c [entity] use role instead of x
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2931
diff changeset
    96
            if role == 'subject':
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    97
                setattr(cls, rschema.type, SubjectRelation(rschema))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    98
            else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    99
                attr = 'reverse_%s' % rschema.type
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   100
                setattr(cls, attr, ObjectRelation(rschema))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   101
        if mixins:
3919
f91bd15f427c fix nasty pluggable mixins bug, where mixins take precedence other user class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   102
            # see etype class instantation in cwvreg.ETypeRegistry.etype_class method:
f91bd15f427c fix nasty pluggable mixins bug, where mixins take precedence other user class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   103
            # due to class dumping, cls is the generated top level class with actual
f91bd15f427c fix nasty pluggable mixins bug, where mixins take precedence other user class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   104
            # user class as (only) parent. Since we want to be able to override mixins
f91bd15f427c fix nasty pluggable mixins bug, where mixins take precedence other user class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   105
            # method from this user class, we have to take care to insert mixins after that
f91bd15f427c fix nasty pluggable mixins bug, where mixins take precedence other user class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   106
            # class
f91bd15f427c fix nasty pluggable mixins bug, where mixins take precedence other user class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   107
            #
f91bd15f427c fix nasty pluggable mixins bug, where mixins take precedence other user class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   108
            # note that we don't plug mixins as user class parent since it causes pb
f91bd15f427c fix nasty pluggable mixins bug, where mixins take precedence other user class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   109
            # with some cases of entity classes inheritance.
f91bd15f427c fix nasty pluggable mixins bug, where mixins take precedence other user class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   110
            mixins.insert(0, cls.__bases__[0])
f91bd15f427c fix nasty pluggable mixins bug, where mixins take precedence other user class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   111
            mixins += cls.__bases__[1:]
f91bd15f427c fix nasty pluggable mixins bug, where mixins take precedence other user class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   112
            cls.__bases__ = tuple(mixins)
f91bd15f427c fix nasty pluggable mixins bug, where mixins take precedence other user class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   113
            cls.info('plugged %s mixins on %s', mixins, cls)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   114
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   115
    @classmethod
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   116
    def fetch_rql(cls, user, restriction=None, fetchattrs=None, mainvar='X',
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   117
                  settype=True, ordermethod='fetch_order'):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   118
        """return a rql to fetch all entities of the class type"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   119
        restrictions = restriction or []
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   120
        if settype:
3376
f5c69485381f [appobjects] use __regid__ instead of __id__, more explicit
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3369
diff changeset
   121
            restrictions.append('%s is %s' % (mainvar, cls.__regid__))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   122
        if fetchattrs is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   123
            fetchattrs = cls.fetch_attrs
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   124
        selection = [mainvar]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   125
        orderby = []
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   126
        # start from 26 to avoid possible conflicts with X
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   127
        varmaker = rqlvar_maker(index=26)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   128
        cls._fetch_restrictions(mainvar, varmaker, fetchattrs, selection,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   129
                                orderby, restrictions, user, ordermethod)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   130
        rql = 'Any %s' % ','.join(selection)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   131
        if orderby:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   132
            rql +=  ' ORDERBY %s' % ','.join(orderby)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   133
        rql += ' WHERE %s' % ', '.join(restrictions)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   134
        return rql
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   135
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   136
    @classmethod
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   137
    def _fetch_restrictions(cls, mainvar, varmaker, fetchattrs,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   138
                            selection, orderby, restrictions, user,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   139
                            ordermethod='fetch_order', visited=None):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   140
        eschema = cls.e_schema
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   141
        if visited is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   142
            visited = set((eschema.type,))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   143
        elif eschema.type in visited:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   144
            # avoid infinite recursion
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   145
            return
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   146
        else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   147
            visited.add(eschema.type)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   148
        _fetchattrs = []
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   149
        for attr in fetchattrs:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   150
            try:
3689
deb13e88e037 follow yams 0.25 api changes to improve performance
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3683
diff changeset
   151
                rschema = eschema.subjrels[attr]
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   152
            except KeyError:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   153
                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
   154
                            attr, cls.__regid__)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   155
                continue
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   156
            rdef = eschema.rdef(attr)
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   157
            if not user.matching_groups(rdef.get_groups('read')):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   158
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   159
            var = varmaker.next()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   160
            selection.append(var)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   161
            restriction = '%s %s %s' % (mainvar, attr, var)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   162
            restrictions.append(restriction)
3689
deb13e88e037 follow yams 0.25 api changes to improve performance
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3683
diff changeset
   163
            if not rschema.final:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   164
                # XXX this does not handle several destination types
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   165
                desttype = rschema.objects(eschema.type)[0]
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   166
                card = rdef.cardinality[0]
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   167
                if card not in '?1':
2928
edfdb69df6e8 oops, not self but cls here
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2877
diff changeset
   168
                    cls.warning('bad relation %s specified in fetch attrs for %s',
edfdb69df6e8 oops, not self but cls here
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2877
diff changeset
   169
                                 attr, cls)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   170
                    selection.pop()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   171
                    restrictions.pop()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   172
                    continue
2871
83c5499e1436 [entity] fix fetch_rql w/ case where it's called while entity is not 'complete' (eg time where it's being added but have not yet all mandatory relations set)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2658
diff changeset
   173
                # 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
   174
                # (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
   175
                # 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
   176
                # later information here, systematically add it.
83c5499e1436 [entity] fix fetch_rql w/ case where it's called while entity is not 'complete' (eg time where it's being added but have not yet all mandatory relations set)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2658
diff changeset
   177
                restrictions[-1] += '?'
4049
5838a4b0766d 3.5 api update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4023
diff changeset
   178
                # XXX user._cw.vreg iiiirk
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   179
                destcls = user._cw.vreg['etypes'].etype_class(desttype)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   180
                destcls._fetch_restrictions(var, varmaker, destcls.fetch_attrs,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   181
                                            selection, orderby, restrictions,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   182
                                            user, ordermethod, visited=visited)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   183
            orderterm = getattr(cls, ordermethod)(attr, var)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   184
            if orderterm:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   185
                orderby.append(orderterm)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   186
        return selection, orderby, restrictions
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   187
1471
c889c3bcf5ec new parent_classes method (cached)
sylvain.thenault@logilab.fr
parents: 1435
diff changeset
   188
    @classmethod
c889c3bcf5ec new parent_classes method (cached)
sylvain.thenault@logilab.fr
parents: 1435
diff changeset
   189
    @cached
1840
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   190
    def _rest_attr_info(cls):
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   191
        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
   192
        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
   193
            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
   194
            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
   195
        else:
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   196
            for rschema in cls.e_schema.subject_relations():
3689
deb13e88e037 follow yams 0.25 api changes to improve performance
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3683
diff changeset
   197
                if rschema.final and rschema != 'eid' and cls.e_schema.has_unique_values(rschema):
1840
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   198
                    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
   199
                    needcheck = False
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   200
                    break
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   201
        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
   202
            needcheck = False
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   203
        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
   204
1435
6cd6172718bb allow to instantiate an entity without rset
sylvain.thenault@logilab.fr
parents: 1363
diff changeset
   205
    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
   206
        AppObject.__init__(self, req, rset=rset, row=row, col=col)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   207
        dict.__init__(self)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   208
        self._related_cache = {}
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   209
        if rset is not None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   210
            self.eid = rset[row][col]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   211
        else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   212
            self.eid = None
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   213
        self._is_saved = True
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   214
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   215
    def __repr__(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   216
        return '<Entity %s %s %s at %s>' % (
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   217
            self.e_schema, self.eid, self.keys(), id(self))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   218
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   219
    def __nonzero__(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   220
        return True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   221
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   222
    def __hash__(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   223
        return id(self)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   224
3047
ba86b1bdbcab fix __cmp__ arguments
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3000
diff changeset
   225
    def __cmp__(self, other):
3000
4e76477949d5 B [entities] #343385 comparing entities should raise NotImplementedError
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2928
diff changeset
   226
        raise NotImplementedError('comparison not implemented for %s' % self.__class__)
4e76477949d5 B [entities] #343385 comparing entities should raise NotImplementedError
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2928
diff changeset
   227
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   228
    def pre_add_hook(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   229
        """hook called by the repository before doing anything to add the entity
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   230
        (before_add entity hooks have not been called yet). This give the
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   231
        occasion to do weird stuff such as autocast (File -> Image for instance).
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   232
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   233
        This method must return the actual entity to be added.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   234
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   235
        return self
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   236
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   237
    def set_eid(self, eid):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   238
        self.eid = self['eid'] = eid
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   239
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   240
    def has_eid(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   241
        """return True if the entity has an attributed eid (False
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   242
        meaning that the entity has to be created
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   243
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   244
        try:
3664
af7ca3597b8d use typed_eid
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3626
diff changeset
   245
            typed_eid(self.eid)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   246
            return True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   247
        except (ValueError, TypeError):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   248
            return False
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   249
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   250
    def is_saved(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   251
        """during entity creation, there is some time during which the entity
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   252
        has an eid attributed though it's not saved (eg during before_add_entity
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   253
        hooks). You can use this method to ensure the entity has an eid *and* is
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   254
        saved in its source.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   255
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   256
        return self.has_eid() and self._is_saved
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   257
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   258
    @cached
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   259
    def metainformation(self):
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   260
        res = dict(zip(('type', 'source', 'extid'), self._cw.describe(self.eid)))
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   261
        res['source'] = self._cw.source_defs()[res['source']]
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   262
        return res
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   263
475
b32a5772ff06 should clear local perm cache if first attempt failed
sylvain.thenault@logilab.fr
parents: 413
diff changeset
   264
    def clear_local_perm_cache(self, action):
b32a5772ff06 should clear local perm cache if first attempt failed
sylvain.thenault@logilab.fr
parents: 413
diff changeset
   265
        for rqlexpr in self.e_schema.get_rqlexprs(action):
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   266
            self._cw.local_perm_cache.pop((rqlexpr.eid, (('x', self.eid),)), None)
475
b32a5772ff06 should clear local perm cache if first attempt failed
sylvain.thenault@logilab.fr
parents: 413
diff changeset
   267
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   268
    def 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
   269
        self.e_schema.check_perm(self._cw, action, eid=self.eid)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   270
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   271
    def 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
   272
        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
   273
4406
b3f61c38526b [entity] rename vid argument of .view(...) into __vid to avoid potential conflicts with kwargs
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4212
diff changeset
   274
    def view(self, __vid, __registry='views', **kwargs):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   275
        """shortcut to apply a view on this entity"""
4451
65f4665233e6 misc typos found on my way: NameError / SyntaxError / double __select__, <sigh ...>
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4436
diff changeset
   276
        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
   277
                                                row=self.cw_row, col=self.cw_col,
e134d2dd9992 [entity] pass cw_row and cw_col to select(vid, ...) in self.view
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3452
diff changeset
   278
                                                **kwargs)
3418
7b49fa7e942d [api] use _cw, cw_row, cw_col, cw_rset etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3405
diff changeset
   279
        return view.render(row=self.cw_row, col=self.cw_col, **kwargs)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   280
2059
af33833d7571 absolute_url / build_url refactoring to avoid potential name clash
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2058
diff changeset
   281
    def absolute_url(self, *args, **kwargs):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   282
        """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
   283
        # 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
   284
        # 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
   285
        if args:
af33833d7571 absolute_url / build_url refactoring to avoid potential name clash
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2058
diff changeset
   286
            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
   287
            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
   288
        else:
af33833d7571 absolute_url / build_url refactoring to avoid potential name clash
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2058
diff changeset
   289
            method = None
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   290
        # in linksearch mode, we don't want external urls else selecting
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   291
        # the object for use in the relation is tricky
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   292
        # XXX search_state is web specific
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   293
        if getattr(self._cw, 'search_state', ('normal',))[0] == 'normal':
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   294
            kwargs['base_url'] = self.metainformation()['source'].get('base-url')
1904
e23536d29231 minor refactoring of absolute_url()
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 1842
diff changeset
   295
        if method in (None, 'view'):
1842
c7a22540d6f7 add some bw compat code for old rest_path prototype
sylvain.thenault@logilab.fr
parents: 1840
diff changeset
   296
            try:
c7a22540d6f7 add some bw compat code for old rest_path prototype
sylvain.thenault@logilab.fr
parents: 1840
diff changeset
   297
                kwargs['_restpath'] = self.rest_path(kwargs.get('base_url'))
c7a22540d6f7 add some bw compat code for old rest_path prototype
sylvain.thenault@logilab.fr
parents: 1840
diff changeset
   298
            except TypeError:
3405
9d31c9cb8103 nicer deprecation warnings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3382
diff changeset
   299
                warn('[3.4] %s: rest_path() now take use_ext_eid argument, '
3376
f5c69485381f [appobjects] use __regid__ instead of __id__, more explicit
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3369
diff changeset
   300
                     'please update' % self.__regid__, DeprecationWarning)
1842
c7a22540d6f7 add some bw compat code for old rest_path prototype
sylvain.thenault@logilab.fr
parents: 1840
diff changeset
   301
                kwargs['_restpath'] = self.rest_path()
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   302
        else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   303
            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
   304
        return self._cw.build_url(method, **kwargs)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   305
1840
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   306
    def rest_path(self, use_ext_eid=False):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   307
        """returns a REST-like (relative) path for this entity"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   308
        mainattr, needcheck = self._rest_attr_info()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   309
        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
   310
        path = etype.lower()
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   311
        if mainattr != 'eid':
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   312
            value = getattr(self, mainattr)
2125
19861294506f https://www.logilab.net/cwo/ticket/343724
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2005
diff changeset
   313
            if value is None or unicode(value) == u'':
1840
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   314
                mainattr = 'eid'
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   315
                path += '/eid'
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   316
            elif needcheck:
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   317
                # 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
   318
                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
   319
                    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
   320
                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
   321
                    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
   322
                        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
   323
                    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
   324
                if nbresults != 1: # ambiguity?
e23536d29231 minor refactoring of absolute_url()
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 1842
diff changeset
   325
                    mainattr = 'eid'
e23536d29231 minor refactoring of absolute_url()
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 1842
diff changeset
   326
                    path += '/eid'
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   327
        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
   328
            if use_ext_eid:
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   329
                value = self.metainformation()['extid']
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   330
            else:
f4b5c15d1147 test and fix #342997: local eid used for absolute_url of external entities
sylvain.thenault@logilab.fr
parents: 1804
diff changeset
   331
                value = self.eid
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   332
        return '%s/%s' % (path, self._cw.url_quote(value))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   333
1360
13ae1121835e rename attribute_metadata method to attr_metadata to save a few chars
sylvain.thenault@logilab.fr
parents: 1313
diff changeset
   334
    def attr_metadata(self, attr, metadata):
1101
0c067de38e46 unification of meta-attributes handling:
sylvain.thenault@logilab.fr
parents: 1098
diff changeset
   335
        """return a metadata for an attribute (None if unspecified)"""
0c067de38e46 unification of meta-attributes handling:
sylvain.thenault@logilab.fr
parents: 1098
diff changeset
   336
        value = getattr(self, '%s_%s' % (attr, metadata), None)
0c067de38e46 unification of meta-attributes handling:
sylvain.thenault@logilab.fr
parents: 1098
diff changeset
   337
        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
   338
            value = self._cw.vreg.property_value('ui.encoding')
1101
0c067de38e46 unification of meta-attributes handling:
sylvain.thenault@logilab.fr
parents: 1098
diff changeset
   339
        return value
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   340
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   341
    def printable_value(self, attr, value=_marker, attrtype=None,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   342
                        format='text/html', displaytime=True):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   343
        """return a displayable value (i.e. unicode string) which may contains
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   344
        html tags
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   345
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   346
        attr = str(attr)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   347
        if value is _marker:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   348
            value = getattr(self, attr)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   349
        if isinstance(value, basestring):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   350
            value = value.strip()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   351
        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
   352
            return u''
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   353
        if attrtype is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   354
            attrtype = self.e_schema.destination(attr)
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   355
        props = self.e_schema.rdef(attr)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   356
        if attrtype == 'String':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   357
            # internalinalized *and* formatted string such as schema
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   358
            # description...
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   359
            if props.internationalizable:
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   360
                value = self._cw._(value)
1360
13ae1121835e rename attribute_metadata method to attr_metadata to save a few chars
sylvain.thenault@logilab.fr
parents: 1313
diff changeset
   361
            attrformat = self.attr_metadata(attr, 'format')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   362
            if attrformat:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   363
                return self.mtc_transform(value, attrformat, format,
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   364
                                          self._cw.encoding)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   365
        elif attrtype == 'Bytes':
1360
13ae1121835e rename attribute_metadata method to attr_metadata to save a few chars
sylvain.thenault@logilab.fr
parents: 1313
diff changeset
   366
            attrformat = self.attr_metadata(attr, 'format')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   367
            if attrformat:
1360
13ae1121835e rename attribute_metadata method to attr_metadata to save a few chars
sylvain.thenault@logilab.fr
parents: 1313
diff changeset
   368
                encoding = self.attr_metadata(attr, 'encoding')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   369
                return self.mtc_transform(value.getvalue(), attrformat, format,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   370
                                          encoding)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   371
            return u''
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   372
        value = printable_value(self._cw, attrtype, value, props,
3212
07d11bacfefe displaytime attribute should not have been removed from there
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3184
diff changeset
   373
                                displaytime=displaytime)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   374
        if format == 'text/html':
2312
af4d8f75c5db use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2125
diff changeset
   375
            value = xml_escape(value)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   376
        return value
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   377
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   378
    def mtc_transform(self, data, format, target_format, encoding,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   379
                      _engine=ENGINE):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   380
        trdata = TransformData(data, format, encoding, appobject=self)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   381
        data = _engine.convert(trdata, target_format).decode()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   382
        if format == 'text/html':
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   383
            data = soup2xhtml(data, self._cw.encoding)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   384
        return data
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   385
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   386
    # entity cloning ##########################################################
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   387
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   388
    def copy_relations(self, ceid):
3626
017869a514c3 [doc] updated docstrings
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 3552
diff changeset
   389
        """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
   390
        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
   391
        ceid designates the original entity).
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   392
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   393
        By default meta and composite relations are skipped.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   394
        Overrides this if you want another behaviour
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   395
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   396
        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
   397
        execute = self._cw.execute
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   398
        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
   399
            if rschema.final or rschema.meta:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   400
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   401
            # skip already defined relations
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   402
            if getattr(self, rschema.type):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   403
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   404
            if rschema.type in self.skip_copy_for:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   405
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   406
            # skip composite relation
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   407
            rdef = self.e_schema.rdef(rschema)
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   408
            if rdef.composite:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   409
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   410
            # skip relation with card in ?1 else we either change the copied
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   411
            # object (inlined relation) or inserting some inconsistency
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   412
            if rdef.cardinality[1] in '?1':
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   413
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   414
            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
   415
                rschema.type, rschema.type)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   416
            execute(rql, {'x': self.eid, 'y': ceid}, ('x', 'y'))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   417
            self.clear_related_cache(rschema.type, 'subject')
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   418
        for rschema in self.e_schema.object_relations():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   419
            if rschema.meta:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   420
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   421
            # skip already defined relations
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   422
            if self.related(rschema.type, 'object'):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   423
                continue
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   424
            rdef = self.e_schema.rdef(rschema, 'object')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   425
            # skip composite relation
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   426
            if rdef.composite:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   427
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   428
            # skip relation with card in ?1 else we either change the copied
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   429
            # object (inlined relation) or inserting some inconsistency
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   430
            if rdef.cardinality[0] in '?1':
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   431
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   432
            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
   433
                rschema.type, rschema.type)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   434
            execute(rql, {'x': self.eid, 'y': ceid}, ('x', 'y'))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   435
            self.clear_related_cache(rschema.type, 'object')
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   436
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   437
    # data fetching methods ###################################################
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   438
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   439
    @cached
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   440
    def as_rset(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   441
        """returns a resultset containing `self` information"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   442
        rset = ResultSet([(self.eid,)], 'Any X WHERE X eid %(x)s',
3376
f5c69485381f [appobjects] use __regid__ instead of __id__, more explicit
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3369
diff changeset
   443
                         {'x': self.eid}, [(self.__regid__,)])
4850
bd640b137f50 [refactor] drop rset.vreg attribute, vreg should be accessed through rset.req. Also kill decorate_rset, simply set rset.req where we were calling this method.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4848
diff changeset
   444
        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
   445
        return rset
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   446
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   447
    def to_complete_relations(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   448
        """by default complete final relations to when calling .complete()"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   449
        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
   450
            if rschema.final:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   451
                continue
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   452
            targets = rschema.objects(self.e_schema)
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   453
            if len(targets) > 1:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   454
                # ambigous relations, the querier doesn't handle
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   455
                # outer join correctly in this case
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   456
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   457
            if rschema.inlined:
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   458
                matching_groups = self._cw.user.matching_groups
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   459
                rdef = rschema.rdef(self.e_schema, targets[0])
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   460
                if matching_groups(rdef.get_groups('read')) and \
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   461
                   all(matching_groups(e.get_groups('read')) for e in targets):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   462
                    yield rschema, 'subject'
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   463
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4850
diff changeset
   464
    def to_complete_attributes(self, skip_bytes=True, skip_pwd=True):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   465
        for rschema, attrschema in self.e_schema.attribute_definitions():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   466
            # skip binary data by default
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   467
            if skip_bytes and attrschema.type == 'Bytes':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   468
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   469
            attr = rschema.type
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   470
            if attr == 'eid':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   471
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   472
            # password retreival is blocked at the repository server level
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   473
            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
   474
            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
   475
                   or (attrschema.type == 'Password' and skip_pwd):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   476
                self[attr] = None
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   477
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   478
            yield attr
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   479
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
   480
    _cw_completed = False
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4850
diff changeset
   481
    def complete(self, attributes=None, skip_bytes=True, skip_pwd=True):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   482
        """complete this entity by adding missing attributes (i.e. query the
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   483
        repository to fill the entity)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   484
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   485
        :type skip_bytes: bool
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   486
        :param skip_bytes:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   487
          if true, attribute of type Bytes won't be considered
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   488
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   489
        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
   490
        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
   491
            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
   492
        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
   493
            self._cw_completed = True
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   494
        varmaker = rqlvar_maker()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   495
        V = varmaker.next()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   496
        rql = ['WHERE %s eid %%(x)s' % V]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   497
        selected = []
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4850
diff changeset
   498
        for attr in (attributes or self.to_complete_attributes(skip_bytes, skip_pwd)):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   499
            # if attribute already in entity, nothing to do
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   500
            if self.has_key(attr):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   501
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   502
            # case where attribute must be completed, but is not yet in entity
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   503
            var = varmaker.next()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   504
            rql.append('%s %s %s' % (V, attr, var))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   505
            selected.append((attr, var))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   506
        # +1 since this doen't include the main variable
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   507
        lastattr = len(selected) + 1
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   508
        if attributes is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   509
            # fetch additional relations (restricted to 0..1 relations)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   510
            for rschema, role in self.to_complete_relations():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   511
                rtype = rschema.type
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   512
                if self.relation_cached(rtype, role):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   513
                    continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   514
                var = varmaker.next()
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   515
                targettype = rschema.targets(self.e_schema, role)[0]
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   516
                rdef = rschema.role_rdef(self.e_schema, targettype, role)
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   517
                card = rdef.role_cardinality(role)
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   518
                assert card in '1?', '%s %s %s %s' % (self.e_schema, rtype,
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   519
                                                      role, card)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   520
                if role == 'subject':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   521
                    if card == '1':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   522
                        rql.append('%s %s %s' % (V, rtype, var))
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   523
                    else:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   524
                        rql.append('%s %s %s?' % (V, rtype, var))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   525
                else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   526
                    if card == '1':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   527
                        rql.append('%s %s %s' % (var, rtype, V))
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   528
                    else:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   529
                        rql.append('%s? %s %s' % (var, rtype, V))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   530
                selected.append(((rtype, role), var))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   531
        if selected:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   532
            # select V, we need it as the left most selected variable
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   533
            # if some outer join are included to fetch inlined relations
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   534
            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
   535
                                    ','.join(rql))
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
   536
            rset = self._cw.execute(rql, {'x': self.eid}, 'x',
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
   537
                                    build_descr=False)[0]
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   538
            # handle attributes
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   539
            for i in xrange(1, lastattr):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   540
                self[str(selected[i-1][0])] = rset[i]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   541
            # handle relations
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   542
            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
   543
                rtype, role = selected[i-1][0]
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   544
                value = rset[i]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   545
                if value is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   546
                    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
   547
                    rrset.req = self._cw
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   548
                else:
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   549
                    rrset = self._cw.eid_rset(value)
2941
196493bd099c [entity] use role instead of x
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2931
diff changeset
   550
                self.set_related_cache(rtype, role, rrset)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   551
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   552
    def get_value(self, name):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   553
        """get value for the attribute relation <name>, query the repository
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   554
        to get the value if necessary.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   555
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   556
        :type name: str
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   557
        :param name: name of the attribute to get
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   558
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   559
        try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   560
            value = self[name]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   561
        except KeyError:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   562
            if not self.is_saved():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   563
                return None
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   564
            rql = "Any A WHERE X eid %%(x)s, X %s A" % name
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   565
            try:
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
   566
                rset = self._cw.execute(rql, {'x': self.eid}, 'x')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   567
            except Unauthorized:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   568
                self[name] = value = None
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   569
            else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   570
                assert rset.rowcount <= 1, (self, rql, rset.rowcount)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   571
                try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   572
                    self[name] = value = rset.rows[0][0]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   573
                except IndexError:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   574
                    # probably a multisource error
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   575
                    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
   576
                                  name, self.eid)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   577
                    if self.e_schema.destination(name) == 'String':
2320
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2312
diff changeset
   578
                        # XXX (syt) imo emtpy string is better
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   579
                        self[name] = value = self._cw._('unaccessible')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   580
                    else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   581
                        self[name] = value = None
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   582
        return value
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   583
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   584
    def related(self, rtype, role='subject', limit=None, entities=False):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   585
        """returns a resultset of related entities
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   586
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   587
        :param role: is the role played by 'self' in the relation ('subject' or 'object')
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   588
        :param limit: resultset's maximum size
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   589
        :param entities: if True, the entites are returned; if False, a result set is returned
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   590
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   591
        try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   592
            return self.related_cache(rtype, role, entities, limit)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   593
        except KeyError:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   594
            pass
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   595
        assert self.has_eid()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   596
        rql = self.related_rql(rtype, role)
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
   597
        rset = self._cw.execute(rql, {'x': self.eid}, 'x')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   598
        self.set_related_cache(rtype, role, rset)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   599
        return self.related(rtype, role, limit, entities)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   600
3130
2486163c4630 allow to specify targettypes in related_rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3047
diff changeset
   601
    def related_rql(self, rtype, role='subject', targettypes=None):
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   602
        rschema = self._cw.vreg.schema[rtype]
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   603
        if role == 'subject':
3672
554a588ffaea [entity] make related_rql honors its targettypes argument
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3671
diff changeset
   604
            restriction = 'E eid %%(x)s, E %s X' % rtype
3130
2486163c4630 allow to specify targettypes in related_rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3047
diff changeset
   605
            if targettypes is None:
2486163c4630 allow to specify targettypes in related_rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3047
diff changeset
   606
                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
   607
            else:
3683
2e4794c97cf4 fix related_rql when target_type specified
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 3680
diff changeset
   608
                restriction += ', X is IN (%s)' % ','.join(targettypes)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   609
            card = greater_card(rschema, (self.e_schema,), targettypes, 0)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   610
        else:
3672
554a588ffaea [entity] make related_rql honors its targettypes argument
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3671
diff changeset
   611
            restriction = 'E eid %%(x)s, X %s E' % rtype
3130
2486163c4630 allow to specify targettypes in related_rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3047
diff changeset
   612
            if targettypes is None:
2486163c4630 allow to specify targettypes in related_rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3047
diff changeset
   613
                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
   614
            else:
3683
2e4794c97cf4 fix related_rql when target_type specified
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 3680
diff changeset
   615
                restriction += ', X is IN (%s)' % ','.join(targettypes)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   616
            card = greater_card(rschema, targettypes, (self.e_schema,), 1)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   617
        if len(targettypes) > 1:
413
a7366dd3c33c fix bug in entity.related_rql(): fetch_attr list / fetchorder weren't computed correctly
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 397
diff changeset
   618
            fetchattrs_list = []
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   619
            for ttype in targettypes:
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   620
                etypecls = self._cw.vreg['etypes'].etype_class(ttype)
413
a7366dd3c33c fix bug in entity.related_rql(): fetch_attr list / fetchorder weren't computed correctly
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 397
diff changeset
   621
                fetchattrs_list.append(set(etypecls.fetch_attrs))
a7366dd3c33c fix bug in entity.related_rql(): fetch_attr list / fetchorder weren't computed correctly
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 397
diff changeset
   622
            fetchattrs = reduce(set.intersection, fetchattrs_list)
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   623
            rql = etypecls.fetch_rql(self._cw.user, [restriction], fetchattrs,
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   624
                                     settype=False)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   625
        else:
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   626
            etypecls = self._cw.vreg['etypes'].etype_class(targettypes[0])
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   627
            rql = etypecls.fetch_rql(self._cw.user, [restriction], settype=False)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   628
        # optimisation: remove ORDERBY if cardinality is 1 or ? (though
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   629
        # greater_card return 1 for those both cases)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   630
        if card == '1':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   631
            if ' ORDERBY ' in rql:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   632
                rql = '%s WHERE %s' % (rql.split(' ORDERBY ', 1)[0],
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   633
                                       rql.split(' WHERE ', 1)[1])
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   634
        elif not ' ORDERBY ' in rql:
4630
528dee042927 fix #694445: related entity generates weird RQL which in turn generates weird SQL which fails on SQL Server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4460
diff changeset
   635
            args = rql.split(' WHERE ', 1)
528dee042927 fix #694445: related entity generates weird RQL which in turn generates weird SQL which fails on SQL Server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4460
diff changeset
   636
            # if modification_date already retreived, we should use it instead
528dee042927 fix #694445: related entity generates weird RQL which in turn generates weird SQL which fails on SQL Server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4460
diff changeset
   637
            # of adding another variable for sort. This should be be problematic
528dee042927 fix #694445: related entity generates weird RQL which in turn generates weird SQL which fails on SQL Server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4460
diff changeset
   638
            # but it's actually with sqlserver, see ticket #694445
528dee042927 fix #694445: related entity generates weird RQL which in turn generates weird SQL which fails on SQL Server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4460
diff changeset
   639
            if 'X modification_date ' in args[1]:
528dee042927 fix #694445: related entity generates weird RQL which in turn generates weird SQL which fails on SQL Server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4460
diff changeset
   640
                var = args[1].split('X modification_date ', 1)[1].split(',', 1)[0]
528dee042927 fix #694445: related entity generates weird RQL which in turn generates weird SQL which fails on SQL Server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4460
diff changeset
   641
                args.insert(1, var.strip())
528dee042927 fix #694445: related entity generates weird RQL which in turn generates weird SQL which fails on SQL Server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4460
diff changeset
   642
                rql = '%s ORDERBY %s DESC WHERE %s' % tuple(args)
528dee042927 fix #694445: related entity generates weird RQL which in turn generates weird SQL which fails on SQL Server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4460
diff changeset
   643
            else:
528dee042927 fix #694445: related entity generates weird RQL which in turn generates weird SQL which fails on SQL Server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4460
diff changeset
   644
                rql = '%s ORDERBY Z DESC WHERE X modification_date Z, %s' % \
528dee042927 fix #694445: related entity generates weird RQL which in turn generates weird SQL which fails on SQL Server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4460
diff changeset
   645
                      tuple(args)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   646
        return rql
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   647
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   648
    # generic vocabulary methods ##############################################
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   649
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   650
    def unrelated_rql(self, rtype, targettype, role, ordermethod=None,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   651
                      vocabconstraints=True):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   652
        """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
   653
        using (rtype, role) relation.
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
   654
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
   655
        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
   656
        linked by `rtype`.
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   657
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   658
        ordermethod = ordermethod or 'fetch_unrelated_order'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   659
        if isinstance(rtype, basestring):
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   660
            rtype = self._cw.vreg.schema.rschema(rtype)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   661
        if role == 'subject':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   662
            evar, searchedvar = 'S', 'O'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   663
            subjtype, objtype = self.e_schema, targettype
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   664
        else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   665
            searchedvar, evar = 'S', 'O'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   666
            objtype, subjtype = self.e_schema, targettype
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   667
        if self.has_eid():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   668
            restriction = ['NOT S %s O' % rtype, '%s eid %%(x)s' % evar]
3241
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
   669
            args = {'x': self.eid}
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
   670
            if role == 'subject':
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
   671
                securitycheck_args = {'fromeid': self.eid}
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
   672
            else:
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
   673
                securitycheck_args = {'toeid': self.eid}
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   674
        else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   675
            restriction = []
3241
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
   676
            args = {}
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
   677
            securitycheck_args = {}
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   678
        rdef = rtype.role_rdef(self.e_schema, targettype, role)
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   679
        insertsecurity = (rdef.has_local_role('add') and not
3890
d7a270f50f54 backport stable branch (one more time painfully)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3777 3877
diff changeset
   680
                          rdef.has_perm(self._cw, 'add', **securitycheck_args))
3961
d1cbf77db999 fix RQLUniqueConstraint behaviour by using a DISTINCT query and allowing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3955
diff changeset
   681
        # XXX consider constraint.mainvars to check if constraint apply
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   682
        if vocabconstraints:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   683
            # RQLConstraint is a subclass for RQLVocabularyConstraint, so they
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   684
            # will be included as well
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   685
            restriction += [cstr.restriction for cstr in rdef.constraints
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   686
                            if isinstance(cstr, RQLVocabularyConstraint)]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   687
        else:
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   688
            restriction += [cstr.restriction for cstr in rdef.constraints
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   689
                            if isinstance(cstr, RQLConstraint)]
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   690
        etypecls = self._cw.vreg['etypes'].etype_class(targettype)
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   691
        rql = etypecls.fetch_rql(self._cw.user, restriction,
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   692
                                 mainvar=searchedvar, ordermethod=ordermethod)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   693
        # ensure we have an order defined
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   694
        if not ' ORDERBY ' in rql:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   695
            before, after = rql.split(' WHERE ', 1)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   696
            rql = '%s ORDERBY %s WHERE %s' % (before, searchedvar, after)
3241
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
   697
        if insertsecurity:
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   698
            rqlexprs = rdef.get_rqlexprs('add')
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   699
            rewriter = RQLRewriter(self._cw)
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   700
            rqlst = self._cw.vreg.parse(self._cw, rql, args)
3826
0c0c051863cb close #511810: bad rql generated when looking for vocabulary for a relation on an entity which doesn't exist (yet)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3746
diff changeset
   701
            if not self.has_eid():
0c0c051863cb close #511810: bad rql generated when looking for vocabulary for a relation on an entity which doesn't exist (yet)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3746
diff changeset
   702
                existant = searchedvar
0c0c051863cb close #511810: bad rql generated when looking for vocabulary for a relation on an entity which doesn't exist (yet)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3746
diff changeset
   703
            else:
0c0c051863cb close #511810: bad rql generated when looking for vocabulary for a relation on an entity which doesn't exist (yet)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3746
diff changeset
   704
                existant = None # instead of 'SO', improve perfs
3241
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
   705
            for select in rqlst.children:
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
   706
                rewriter.rewrite(select, [((searchedvar, searchedvar), rqlexprs)],
3826
0c0c051863cb close #511810: bad rql generated when looking for vocabulary for a relation on an entity which doesn't exist (yet)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3746
diff changeset
   707
                                 select.solutions, args, existant)
3241
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
   708
            rql = rqlst.as_string()
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
   709
        return rql, args
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   710
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   711
    def unrelated(self, rtype, targettype, role='subject', limit=None,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   712
                  ordermethod=None):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   713
        """return a result set of target type objects that may be related
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   714
        by a given relation, with self as subject or object
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   715
        """
3241
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
   716
        try:
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
   717
            rql, args = self.unrelated_rql(rtype, targettype, role, ordermethod)
1a6f7a0e7dbd unrelated_rql now considers relation's add perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3212
diff changeset
   718
        except Unauthorized:
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   719
            return self._cw.empty_rset()
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   720
        if limit is not None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   721
            before, after = rql.split(' WHERE ', 1)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   722
            rql = '%s LIMIT %s WHERE %s' % (before, limit, after)
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   723
        return self._cw.execute(rql, args, tuple(args))
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   724
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   725
    # relations cache handling ################################################
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   726
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   727
    def relation_cached(self, rtype, role):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   728
        """return true if the given relation is already cached on the instance
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   729
        """
2647
b0a2e779845c enable server side entity caching, 25% speedup on codenaf insertion. ALL CW TESTS OK
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2613
diff changeset
   730
        return self._related_cache.get('%s_%s' % (rtype, role))
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   731
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   732
    def related_cache(self, rtype, role, entities=True, limit=None):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   733
        """return values for the given relation if it's cached on the instance,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   734
        else raise `KeyError`
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   735
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   736
        res = self._related_cache['%s_%s' % (rtype, role)][entities]
3680
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3679
diff changeset
   737
        if limit is not None and limit < len(res):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   738
            if entities:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   739
                res = res[:limit]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   740
            else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   741
                res = res.limit(limit)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   742
        return res
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   743
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   744
    def set_related_cache(self, rtype, role, rset, col=0):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   745
        """set cached values for the given relation"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   746
        if rset:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   747
            related = list(rset.entities(col))
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   748
            rschema = self._cw.vreg.schema.rschema(rtype)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   749
            if role == 'subject':
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   750
                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
   751
                target = 'object'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   752
            else:
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3826
diff changeset
   753
                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
   754
                target = 'subject'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   755
            if rcard in '?1':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   756
                for rentity in related:
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
   757
                    rentity._related_cache['%s_%s' % (rtype, target)] = (
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
   758
                        self.as_rset(), (self,))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   759
        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
   760
            related = ()
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   761
        self._related_cache['%s_%s' % (rtype, role)] = (rset, related)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   762
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   763
    def clear_related_cache(self, rtype=None, role=None):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   764
        """clear cached values for the given relation or the entire cache if
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   765
        no relation is given
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   766
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   767
        if rtype is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   768
            self._related_cache = {}
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   769
        else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   770
            assert role
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   771
            self._related_cache.pop('%s_%s' % (rtype, role), None)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   772
2942
77ebdbe93cf8 [entity] generic clear_all_caches methods, to use in test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2941
diff changeset
   773
    def 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
   774
        """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
   775
        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
   776
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
   777
        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
   778
        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
   779
        """
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
   780
        # clear attributes cache
3665
42f3a66cab51 fix clear_all_cache: ensure we don't remove eid from entity's dict
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3664
diff changeset
   781
        haseid = 'eid' in self
4408
899b426087ab [entity] small optimization: once an entity has been completed, don't redo it (for nothing)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4406
diff changeset
   782
        self._cw_completed = False
2942
77ebdbe93cf8 [entity] generic clear_all_caches methods, to use in test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2941
diff changeset
   783
        self.clear()
3665
42f3a66cab51 fix clear_all_cache: ensure we don't remove eid from entity's dict
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3664
diff changeset
   784
        # set eid if it was in, else we may get nasty error while editing this
42f3a66cab51 fix clear_all_cache: ensure we don't remove eid from entity's dict
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3664
diff changeset
   785
        # entity if it's bound to a repo session
42f3a66cab51 fix clear_all_cache: ensure we don't remove eid from entity's dict
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3664
diff changeset
   786
        if haseid:
42f3a66cab51 fix clear_all_cache: ensure we don't remove eid from entity's dict
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3664
diff changeset
   787
            self['eid'] = self.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
   788
        # clear relations 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
   789
        for rschema, _, role in self.e_schema.relation_definitions():
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
   790
            self.clear_related_cache(rschema.type, role)
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
   791
        # 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
   792
        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
   793
            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
   794
        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
   795
            pass
4759
af2e6c377c71 cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4719
diff changeset
   796
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   797
    # raw edition utilities ###################################################
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   798
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
   799
    def set_attributes(self, **kwargs):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   800
        assert kwargs
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
   801
        _check_cw_unsafe(kwargs)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   802
        relations = []
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   803
        for key in kwargs:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   804
            relations.append('X %s %%(%s)s' % (key, key))
397
cf577e26f924 don't introduce a spurious 'x' key in the entity-as dict
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 237
diff changeset
   805
        # update current local object
cf577e26f924 don't introduce a spurious 'x' key in the entity-as dict
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 237
diff changeset
   806
        self.update(kwargs)
cf577e26f924 don't introduce a spurious 'x' key in the entity-as dict
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 237
diff changeset
   807
        # and now update the database
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   808
        kwargs['x'] = self.eid
4835
13b0b96d7982 [repo] enhanced security handling: deprecates unsafe_execute, in favor of explicit read/write security control using the `enabled_security` context manager. Also code executed on the repository side is now unsafe by default.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4831
diff changeset
   809
        self._cw.execute('SET %s WHERE X eid %%(x)s' % ','.join(relations),
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
   810
                         kwargs, 'x')
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   811
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
   812
    def set_relations(self, **kwargs):
3955
235a9fda6058 support x.set_relations(a_relation=None) to delete a_relation relations from this entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3919
diff changeset
   813
        """add relations to the given object. To set a relation where this entity
235a9fda6058 support x.set_relations(a_relation=None) to delete a_relation relations from this entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3919
diff changeset
   814
        is the object of the relation, use 'reverse_'<relation> as argument name.
235a9fda6058 support x.set_relations(a_relation=None) to delete a_relation relations from this entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3919
diff changeset
   815
235a9fda6058 support x.set_relations(a_relation=None) to delete a_relation relations from this entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3919
diff changeset
   816
        Values may be an entity, a list of entity, or None (meaning that all
235a9fda6058 support x.set_relations(a_relation=None) to delete a_relation relations from this entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3919
diff changeset
   817
        relations of the given type from or to this object should be deleted).
235a9fda6058 support x.set_relations(a_relation=None) to delete a_relation relations from this entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3919
diff changeset
   818
        """
235a9fda6058 support x.set_relations(a_relation=None) to delete a_relation relations from this entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3919
diff changeset
   819
        # XXX update cache
4835
13b0b96d7982 [repo] enhanced security handling: deprecates unsafe_execute, in favor of explicit read/write security control using the `enabled_security` context manager. Also code executed on the repository side is now unsafe by default.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4831
diff changeset
   820
        _check_cw_unsafe(kwargs)
3671
c765adac7f5c new set_relations method on entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3665
diff changeset
   821
        for attr, values in kwargs.iteritems():
c765adac7f5c new set_relations method on entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3665
diff changeset
   822
            if attr.startswith('reverse_'):
c765adac7f5c new set_relations method on entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3665
diff changeset
   823
                restr = 'Y %s X' % attr[len('reverse_'):]
c765adac7f5c new set_relations method on entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3665
diff changeset
   824
            else:
c765adac7f5c new set_relations method on entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3665
diff changeset
   825
                restr = 'X %s Y' % attr
3955
235a9fda6058 support x.set_relations(a_relation=None) to delete a_relation relations from this entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3919
diff changeset
   826
            if values is None:
235a9fda6058 support x.set_relations(a_relation=None) to delete a_relation relations from this entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3919
diff changeset
   827
                execute('DELETE %s WHERE X eid %%(x)s' % restr,
235a9fda6058 support x.set_relations(a_relation=None) to delete a_relation relations from this entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3919
diff changeset
   828
                        {'x': self.eid}, 'x')
235a9fda6058 support x.set_relations(a_relation=None) to delete a_relation relations from this entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3919
diff changeset
   829
                continue
3746
74192424b2c8 accepts single values as create_entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3689
diff changeset
   830
            if not isinstance(values, (tuple, list, set, frozenset)):
74192424b2c8 accepts single values as create_entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3689
diff changeset
   831
                values = (values,)
4835
13b0b96d7982 [repo] enhanced security handling: deprecates unsafe_execute, in favor of explicit read/write security control using the `enabled_security` context manager. Also code executed on the repository side is now unsafe by default.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4831
diff changeset
   832
            self._cw.execute('SET %s WHERE X eid %%(x)s, Y eid IN (%s)' % (
3671
c765adac7f5c new set_relations method on entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3665
diff changeset
   833
                restr, ','.join(str(r.eid) for r in values)),
4835
13b0b96d7982 [repo] enhanced security handling: deprecates unsafe_execute, in favor of explicit read/write security control using the `enabled_security` context manager. Also code executed on the repository side is now unsafe by default.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4831
diff changeset
   834
                             {'x': self.eid}, 'x')
3671
c765adac7f5c new set_relations method on entity
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3665
diff changeset
   835
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
   836
    def delete(self, **kwargs):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   837
        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
   838
        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
   839
                         {'x': self.eid}, **kwargs)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   840
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   841
    # server side utilities ###################################################
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   842
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   843
    def set_defaults(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   844
        """set default values according to the schema"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   845
        self._default_set = set()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   846
        for attr, value in self.e_schema.defaults():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   847
            if not self.has_key(attr):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   848
                self[str(attr)] = value
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   849
                self._default_set.add(attr)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   850
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   851
    def check(self, creation=False):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   852
        """check this entity against its schema. Only final relation
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   853
        are checked here, constraint on actual relations are checked in hooks
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   854
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   855
        # necessary since eid is handled specifically and yams require it to be
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   856
        # in the dictionary
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   857
        if self._cw is None:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   858
            _ = unicode
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   859
        else:
3378
2f25f701301d use ._cw instead of req on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3376
diff changeset
   860
            _ = self._cw._
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   861
        self.e_schema.check(self, creation=creation, _=_)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   862
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   863
    def fti_containers(self, _done=None):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   864
        if _done is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   865
            _done = set()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   866
        _done.add(self.eid)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   867
        containers = tuple(self.e_schema.fulltext_containers())
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   868
        if containers:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   869
            for rschema, target in containers:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   870
                if target == 'object':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   871
                    targets = getattr(self, rschema.type)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   872
                else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   873
                    targets = getattr(self, 'reverse_%s' % rschema)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   874
                for entity in targets:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   875
                    if entity.eid in _done:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   876
                        continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   877
                    for container in entity.fti_containers(_done):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   878
                        yield container
476
62968fa8845c yield self if no ft container found
sylvain.thenault@logilab.fr
parents: 475
diff changeset
   879
                        yielded = True
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   880
        else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   881
            yield self
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   882
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   883
    def get_words(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   884
        """used by the full text indexer to get words to index
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   885
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   886
        this method should only be used on the repository side since it depends
4848
41f84eea63c9 rename logilab.db into logilab.database
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4835
diff changeset
   887
        on the logilab.database package
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   888
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   889
        :rtype: list
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   890
        :return: the list of indexable word of this entity
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   891
        """
4848
41f84eea63c9 rename logilab.db into logilab.database
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4835
diff changeset
   892
        from logilab.database.fti import tokenize
3546
f0aecddf367e fix bug when renaming a full text indexed attribute
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3316
diff changeset
   893
        # take care to cases where we're modyfying the schema
3649
59eb710b9862 3.6 updates
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3629
diff changeset
   894
        pending = self._cw.transaction_data.setdefault('pendingrdefs', set())
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   895
        words = []
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   896
        for rschema in self.e_schema.indexable_attributes():
3546
f0aecddf367e fix bug when renaming a full text indexed attribute
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3316
diff changeset
   897
            if (self.e_schema, rschema) in pending:
f0aecddf367e fix bug when renaming a full text indexed attribute
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3316
diff changeset
   898
                continue
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   899
            try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   900
                value = self.printable_value(rschema, format='text/plain')
1132
96752791c2b6 pylint cleanup
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
   901
            except TransformError:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   902
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   903
            except:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   904
                self.exception("can't add value of %s to text index for entity %s",
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   905
                               rschema, self.eid)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   906
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   907
            if value:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   908
                words += tokenize(value)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   909
        for rschema, role in self.e_schema.fulltext_relations():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   910
            if role == 'subject':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   911
                for entity in getattr(self, rschema.type):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   912
                    words += entity.get_words()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   913
            else: # if role == 'object':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   914
                for entity in getattr(self, 'reverse_%s' % rschema.type):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   915
                    words += entity.get_words()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   916
        return words
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   917
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   918
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   919
# attribute and relation descriptors ##########################################
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   920
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   921
class Attribute(object):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   922
    """descriptor that controls schema attribute access"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   923
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   924
    def __init__(self, attrname):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   925
        assert attrname != 'eid'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   926
        self._attrname = attrname
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   927
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   928
    def __get__(self, eobj, eclass):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   929
        if eobj is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   930
            return self
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   931
        return eobj.get_value(self._attrname)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   932
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   933
    def __set__(self, eobj, value):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   934
        eobj[self._attrname] = value
2875
b7399ef8b3e0 towards better edited attributes handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2872
diff changeset
   935
        if hasattr(eobj, 'edited_attributes'):
b7399ef8b3e0 towards better edited attributes handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2872
diff changeset
   936
            eobj.edited_attributes.add(self._attrname)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   937
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   938
class Relation(object):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   939
    """descriptor that controls schema relation access"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   940
    _role = None # for pylint
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   941
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   942
    def __init__(self, rschema):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   943
        self._rschema = rschema
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   944
        self._rtype = rschema.type
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   945
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   946
    def __get__(self, eobj, eclass):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   947
        if eobj is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   948
            raise AttributeError('%s cannot be only be accessed from instances'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   949
                                 % self._rtype)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   950
        return eobj.related(self._rtype, self._role, entities=True)
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   951
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   952
    def __set__(self, eobj, value):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   953
        raise NotImplementedError
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   954
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   955
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   956
class SubjectRelation(Relation):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   957
    """descriptor that controls schema relation access"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   958
    _role = 'subject'
1474
716f0742ee7f delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1471
diff changeset
   959
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   960
class ObjectRelation(Relation):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   961
    """descriptor that controls schema relation access"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   962
    _role = 'object'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   963
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   964
from logging import getLogger
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   965
from cubicweb import set_log_methods
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   966
set_log_methods(Entity, getLogger('cubicweb.entity'))