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