0
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1
"""Base class for entity objects manipulated in clients
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 2
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 3
:organization: Logilab
479
+ − 4
:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
0
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 5
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 6
"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 7
__docformat__ = "restructuredtext en"
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 8
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 9
from logilab.common import interface
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 10
from logilab.common.compat import all
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 11
from logilab.common.decorators import cached
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 12
from logilab.mtconverter import TransformData , TransformError
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 13
from rql.utils import rqlvar_maker
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 14
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 15
from cubicweb import Unauthorized
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 16
from cubicweb.vregistry import autoselectors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 17
from cubicweb.rset import ResultSet
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 18
from cubicweb.common.appobject import AppRsetObject
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 19
from cubicweb.common.registerers import id_registerer
237
+ − 20
from cubicweb.common.selectors import yes
0
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 21
from cubicweb.common.uilib import printable_value , html_escape , soup2xhtml
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 22
from cubicweb.common.mixins import MI_REL_TRIGGERS
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 23
from cubicweb.common.mttransforms import ENGINE
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 24
from cubicweb.schema import RQLVocabularyConstraint , RQLConstraint , bw_normalize_etype
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 25
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 26
_marker = object ()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 27
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 28
def greater_card ( rschema , subjtypes , objtypes , index ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 29
for subjtype in subjtypes :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 30
for objtype in objtypes :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 31
card = rschema . rproperty ( subjtype , objtype , 'cardinality' )[ index ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 32
if card in '+*' :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 33
return card
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 34
return '1'
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 35
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 36
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 37
class RelationTags ( object ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 38
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 39
MODE_TAGS = frozenset (( 'link' , 'create' ))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 40
CATEGORY_TAGS = frozenset (( 'primary' , 'secondary' , 'generic' , 'generated' ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 41
'inlineview' ))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 42
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 43
def __init__ ( self , eclass , tagdefs ):
979
93447d75c4b9
add an XX message to remember to correct the bug: if a rtag is redefined in a subclass, the rtag of the base class overwrite the rtag of the subclass
Stephanie Marcu <stephanie.marcu@logilab.fr>
diff
changeset
+ − 44
# XXX if a rtag is redefined in a subclass,
93447d75c4b9
add an XX message to remember to correct the bug: if a rtag is redefined in a subclass, the rtag of the base class overwrite the rtag of the subclass
Stephanie Marcu <stephanie.marcu@logilab.fr>
diff
changeset
+ − 45
# the rtag of the base class overwrite the rtag of the subclass
0
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 46
self . eclass = eclass
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 47
self . _tagdefs = {}
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 48
for relation , tags in tagdefs . iteritems ():
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 49
# tags must become a set
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 50
if isinstance ( tags , basestring ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 51
tags = set (( tags ,))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 52
elif not isinstance ( tags , set ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 53
tags = set ( tags )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 54
# relation must become a 3-uple (rtype, targettype, role)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 55
if isinstance ( relation , basestring ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 56
self . _tagdefs [( relation , '*' , 'subject' )] = tags
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 57
self . _tagdefs [( relation , '*' , 'object' )] = tags
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 58
elif len ( relation ) == 1 : # useful ?
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 59
self . _tagdefs [( relation [ 0 ], '*' , 'subject' )] = tags
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 60
self . _tagdefs [( relation [ 0 ], '*' , 'object' )] = tags
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 61
elif len ( relation ) == 2 :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 62
rtype , ttype = relation
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 63
ttype = bw_normalize_etype ( ttype ) # XXX bw compat
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 64
self . _tagdefs [ rtype , ttype , 'subject' ] = tags
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 65
self . _tagdefs [ rtype , ttype , 'object' ] = tags
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 66
elif len ( relation ) == 3 :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 67
relation = list ( relation ) # XXX bw compat
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 68
relation [ 1 ] = bw_normalize_etype ( relation [ 1 ])
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 69
self . _tagdefs [ tuple ( relation )] = tags
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 70
else :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 71
raise ValueError ( 'bad rtag definition ( %r )' % ( relation ,))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 72
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 73
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 74
def __initialize__ ( self ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 75
# eclass.[*]schema are only set when registering
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 76
self . schema = self . eclass . schema
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 77
eschema = self . eschema = self . eclass . e_schema
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 78
rtags = self . _tagdefs
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 79
# expand wildcards in rtags and add automatic tags
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 80
for rschema , tschemas , role in sorted ( eschema . relation_definitions ( True )):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 81
rtype = rschema . type
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 82
star_tags = rtags . pop (( rtype , '*' , role ), set ())
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 83
for tschema in tschemas :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 84
tags = rtags . setdefault (( rtype , tschema . type , role ), set ( star_tags ))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 85
if role == 'subject' :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 86
X , Y = eschema , tschema
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 87
card = rschema . rproperty ( X , Y , 'cardinality' )[ 0 ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 88
composed = rschema . rproperty ( X , Y , 'composite' ) == 'object'
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 89
else :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 90
X , Y = tschema , eschema
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 91
card = rschema . rproperty ( X , Y , 'cardinality' )[ 1 ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 92
composed = rschema . rproperty ( X , Y , 'composite' ) == 'subject'
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 93
# set default category tags if needed
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 94
if not tags & self . CATEGORY_TAGS :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 95
if card in '1+' :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 96
if not rschema . is_final () and composed :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 97
category = 'generated'
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 98
elif rschema . is_final () and (
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 99
rschema . type . endswith ( '_format' )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 100
or rschema . type . endswith ( '_encoding' )):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 101
category = 'generated'
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 102
else :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 103
category = 'primary'
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 104
elif rschema . is_final ():
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 105
if ( rschema . type . endswith ( '_format' )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 106
or rschema . type . endswith ( '_encoding' )):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 107
category = 'generated'
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 108
else :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 109
category = 'secondary'
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 110
else :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 111
category = 'generic'
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 112
tags . add ( category )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 113
if not tags & self . MODE_TAGS :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 114
if card in '?1' :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 115
# by default, suppose link mode if cardinality doesn't allow
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 116
# more than one relation
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 117
mode = 'link'
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 118
elif rschema . rproperty ( X , Y , 'composite' ) == role :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 119
# if self is composed of the target type, create mode
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 120
mode = 'create'
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 121
else :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 122
# link mode by default
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 123
mode = 'link'
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 124
tags . add ( mode )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 125
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 126
def _default_target ( self , rschema , role = 'subject' ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 127
eschema = self . eschema
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 128
if role == 'subject' :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 129
return eschema . subject_relation ( rschema ) . objects ( eschema )[ 0 ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 130
else :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 131
return eschema . object_relation ( rschema ) . subjects ( eschema )[ 0 ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 132
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 133
# dict compat
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 134
def __getitem__ ( self , key ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 135
if isinstance ( key , basestring ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 136
key = ( key ,)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 137
return self . get_tags ( * key )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 138
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 139
__contains__ = __getitem__
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 140
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 141
def get_tags ( self , rtype , targettype = None , role = 'subject' ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 142
rschema = self . schema . rschema ( rtype )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 143
if targettype is None :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 144
tschema = self . _default_target ( rschema , role )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 145
else :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 146
tschema = self . schema . eschema ( targettype )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 147
return self . _tagdefs [( rtype , tschema . type , role )]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 148
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 149
__call__ = get_tags
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 150
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 151
def get_mode ( self , rtype , targettype = None , role = 'subject' ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 152
# XXX: should we make an assertion on rtype not being final ?
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 153
# assert not rschema.is_final()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 154
tags = self . get_tags ( rtype , targettype , role )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 155
# do not change the intersection order !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 156
modes = tags & self . MODE_TAGS
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 157
assert len ( modes ) == 1
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 158
return modes . pop ()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 159
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 160
def get_category ( self , rtype , targettype = None , role = 'subject' ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 161
tags = self . get_tags ( rtype , targettype , role )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 162
categories = tags & self . CATEGORY_TAGS
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 163
assert len ( categories ) == 1
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 164
return categories . pop ()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 165
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 166
def is_inlined ( self , rtype , targettype = None , role = 'subject' ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 167
# return set(('primary', 'secondary')) & self.get_tags(rtype, targettype)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 168
return 'inlineview' in self . get_tags ( rtype , targettype , role )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 169
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 170
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 171
class metaentity ( autoselectors ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 172
"""this metaclass sets the relation tags on the entity class
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 173
and deals with the `widgets` attribute
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 174
"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 175
def __new__ ( mcs , name , bases , classdict ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 176
# collect baseclass' rtags
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 177
tagdefs = {}
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 178
widgets = {}
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 179
for base in bases :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 180
tagdefs . update ( getattr ( base , '__rtags__' , {}))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 181
widgets . update ( getattr ( base , 'widgets' , {}))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 182
# update with the class' own rtgas
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 183
tagdefs . update ( classdict . get ( '__rtags__' , {}))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 184
widgets . update ( classdict . get ( 'widgets' , {}))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 185
# XXX decide whether or not it's a good idea to replace __rtags__
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 186
# good point: transparent support for inheritance levels >= 2
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 187
# bad point: we loose the information of which tags are specific
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 188
# to this entity class
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 189
classdict [ '__rtags__' ] = tagdefs
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 190
classdict [ 'widgets' ] = widgets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 191
eclass = super ( metaentity , mcs ) . __new__ ( mcs , name , bases , classdict )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 192
# adds the "rtags" attribute
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 193
eclass . rtags = RelationTags ( eclass , tagdefs )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 194
return eclass
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 195
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 196
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 197
class Entity ( AppRsetObject , dict ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 198
"""an entity instance has e_schema automagically set on
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 199
the class and instances has access to their issuing cursor.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 200
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 201
A property is set for each attribute and relation on each entity's type
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 202
class. Becare that among attributes, 'eid' is *NEITHER* stored in the
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 203
dict containment (which acts as a cache for other attributes dynamically
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 204
fetched)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 205
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 206
:type e_schema: `cubicweb.schema.EntitySchema`
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 207
:ivar e_schema: the entity's schema
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 208
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 209
:type rest_var: str
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 210
:cvar rest_var: indicates which attribute should be used to build REST urls
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 211
If None is specified, the first non-meta attribute will
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 212
be used
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 213
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 214
:type skip_copy_for: list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 215
:cvar skip_copy_for: a list of relations that should be skipped when copying
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 216
this kind of entity. Note that some relations such
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 217
as composite relations or relations that have '?1' as object
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 218
cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 219
"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 220
__metaclass__ = metaentity
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 221
__registry__ = 'etypes'
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 222
__registerer__ = id_registerer
237
+ − 223
__selectors__ = ( yes ,)
0
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 224
widgets = {}
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 225
id = None
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 226
e_schema = None
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 227
eid = None
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 228
rest_attr = None
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 229
skip_copy_for = ()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 230
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 231
@classmethod
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 232
def registered ( cls , registry ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 233
"""build class using descriptor at registration time"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 234
assert cls . id is not None
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 235
super ( Entity , cls ) . registered ( registry )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 236
if cls . id != 'Any' :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 237
cls . __initialize__ ()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 238
return cls
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 239
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 240
MODE_TAGS = set (( 'link' , 'create' ))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 241
CATEGORY_TAGS = set (( 'primary' , 'secondary' , 'generic' , 'generated' )) # , 'metadata'))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 242
@classmethod
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 243
def __initialize__ ( cls ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 244
"""initialize a specific entity class by adding descriptors to access
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 245
entity type's attributes and relations
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 246
"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 247
etype = cls . id
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 248
assert etype != 'Any' , etype
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 249
cls . e_schema = eschema = cls . schema . eschema ( etype )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 250
for rschema , _ in eschema . attribute_definitions ():
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 251
if rschema . type == 'eid' :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 252
continue
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 253
setattr ( cls , rschema . type , Attribute ( rschema . type ))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 254
mixins = []
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 255
for rschema , _ , x in eschema . relation_definitions ():
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 256
if ( rschema , x ) in MI_REL_TRIGGERS :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 257
mixin = MI_REL_TRIGGERS [( rschema , x )]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 258
if not ( issubclass ( cls , mixin ) or mixin in mixins ): # already mixed ?
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 259
mixins . append ( mixin )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 260
for iface in getattr ( mixin , '__implements__' , ()):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 261
if not interface . implements ( cls , iface ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 262
interface . extend ( cls , iface )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 263
if x == 'subject' :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 264
setattr ( cls , rschema . type , SubjectRelation ( rschema ))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 265
else :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 266
attr = 'reverse_ %s ' % rschema . type
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 267
setattr ( cls , attr , ObjectRelation ( rschema ))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 268
if mixins :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 269
cls . __bases__ = tuple ( mixins + [ p for p in cls . __bases__ if not p is object ])
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 270
cls . debug ( 'plugged %s mixins on %s ' , mixins , etype )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 271
cls . rtags . __initialize__ ()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 272
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 273
@classmethod
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 274
def fetch_rql ( cls , user , restriction = None , fetchattrs = None , mainvar = 'X' ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 275
settype = True , ordermethod = 'fetch_order' ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 276
"""return a rql to fetch all entities of the class type"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 277
restrictions = restriction or []
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 278
if settype :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 279
restrictions . append ( ' %s is %s ' % ( mainvar , cls . id ))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 280
if fetchattrs is None :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 281
fetchattrs = cls . fetch_attrs
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 282
selection = [ mainvar ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 283
orderby = []
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 284
# start from 26 to avoid possible conflicts with X
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 285
varmaker = rqlvar_maker ( index = 26 )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 286
cls . _fetch_restrictions ( mainvar , varmaker , fetchattrs , selection ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 287
orderby , restrictions , user , ordermethod )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 288
rql = 'Any %s ' % ',' . join ( selection )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 289
if orderby :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 290
rql += ' ORDERBY %s ' % ',' . join ( orderby )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 291
rql += ' WHERE %s ' % ', ' . join ( restrictions )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 292
return rql
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 293
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 294
@classmethod
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 295
def _fetch_restrictions ( cls , mainvar , varmaker , fetchattrs ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 296
selection , orderby , restrictions , user ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 297
ordermethod = 'fetch_order' , visited = None ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 298
eschema = cls . e_schema
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 299
if visited is None :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 300
visited = set (( eschema . type ,))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 301
elif eschema . type in visited :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 302
# avoid infinite recursion
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 303
return
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 304
else :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 305
visited . add ( eschema . type )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 306
_fetchattrs = []
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 307
for attr in fetchattrs :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 308
try :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 309
rschema = eschema . subject_relation ( attr )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 310
except KeyError :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 311
cls . warning ( 'skipping fetch_attr %s defined in %s (not found in schema)' ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 312
attr , cls . id )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 313
continue
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 314
if not user . matching_groups ( rschema . get_groups ( 'read' )):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 315
continue
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 316
var = varmaker . next ()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 317
selection . append ( var )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 318
restriction = ' %s %s %s ' % ( mainvar , attr , var )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 319
restrictions . append ( restriction )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 320
if not rschema . is_final ():
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 321
# XXX this does not handle several destination types
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 322
desttype = rschema . objects ( eschema . type )[ 0 ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 323
card = rschema . rproperty ( eschema , desttype , 'cardinality' )[ 0 ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 324
if card not in '?1' :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 325
selection . pop ()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 326
restrictions . pop ()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 327
continue
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 328
if card == '?' :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 329
restrictions [ - 1 ] += '?' # left outer join if not mandatory
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 330
destcls = cls . vreg . etype_class ( desttype )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 331
destcls . _fetch_restrictions ( var , varmaker , destcls . fetch_attrs ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 332
selection , orderby , restrictions ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 333
user , ordermethod , visited = visited )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 334
orderterm = getattr ( cls , ordermethod )( attr , var )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 335
if orderterm :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 336
orderby . append ( orderterm )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 337
return selection , orderby , restrictions
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 338
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 339
def __init__ ( self , req , rset , row = None , col = 0 ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 340
AppRsetObject . __init__ ( self , req , rset )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 341
dict . __init__ ( self )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 342
self . row , self . col = row , col
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 343
self . _related_cache = {}
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 344
if rset is not None :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 345
self . eid = rset [ row ][ col ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 346
else :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 347
self . eid = None
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 348
self . _is_saved = True
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 349
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 350
def __repr__ ( self ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 351
return '<Entity %s %s %s at %s >' % (
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 352
self . e_schema , self . eid , self . keys (), id ( self ))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 353
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 354
def __nonzero__ ( self ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 355
return True
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 356
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 357
def __hash__ ( self ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 358
return id ( self )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 359
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 360
def pre_add_hook ( self ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 361
"""hook called by the repository before doing anything to add the entity
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 362
(before_add entity hooks have not been called yet). This give the
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 363
occasion to do weird stuff such as autocast (File -> Image for instance).
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 364
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 365
This method must return the actual entity to be added.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 366
"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 367
return self
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 368
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 369
def set_eid ( self , eid ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 370
self . eid = self [ 'eid' ] = eid
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 371
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 372
def has_eid ( self ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 373
"""return True if the entity has an attributed eid (False
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 374
meaning that the entity has to be created
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 375
"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 376
try :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 377
int ( self . eid )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 378
return True
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 379
except ( ValueError , TypeError ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 380
return False
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 381
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 382
def is_saved ( self ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 383
"""during entity creation, there is some time during which the entity
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 384
has an eid attributed though it's not saved (eg during before_add_entity
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 385
hooks). You can use this method to ensure the entity has an eid *and* is
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 386
saved in its source.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 387
"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 388
return self . has_eid () and self . _is_saved
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 389
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 390
@cached
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 391
def metainformation ( self ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 392
res = dict ( zip (( 'type' , 'source' , 'extid' ), self . req . describe ( self . eid )))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 393
res [ 'source' ] = self . req . source_defs ()[ res [ 'source' ]]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 394
return res
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 395
475
+ − 396
def clear_local_perm_cache ( self , action ):
+ − 397
for rqlexpr in self . e_schema . get_rqlexprs ( action ):
+ − 398
self . req . local_perm_cache . pop (( rqlexpr . eid , (( 'x' , self . eid ),)), None )
+ − 399
0
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 400
def check_perm ( self , action ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 401
self . e_schema . check_perm ( self . req , action , self . eid )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 402
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 403
def has_perm ( self , action ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 404
return self . e_schema . has_perm ( self . req , action , self . eid )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 405
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 406
def view ( self , vid , __registry = 'views' , ** kwargs ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 407
"""shortcut to apply a view on this entity"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 408
return self . vreg . render ( __registry , vid , self . req , rset = self . rset ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 409
row = self . row , col = self . col , ** kwargs )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 410
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 411
def absolute_url ( self , method = None , ** kwargs ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 412
"""return an absolute url to view this entity"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 413
# in linksearch mode, we don't want external urls else selecting
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 414
# the object for use in the relation is tricky
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 415
# XXX search_state is web specific
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 416
if getattr ( self . req , 'search_state' , ( 'normal' ,))[ 0 ] == 'normal' :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 417
kwargs [ 'base_url' ] = self . metainformation ()[ 'source' ] . get ( 'base-url' )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 418
if method is None or method == 'view' :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 419
kwargs [ '_restpath' ] = self . rest_path ()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 420
else :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 421
kwargs [ 'rql' ] = 'Any X WHERE X eid %s ' % self . eid
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 422
return self . build_url ( method , ** kwargs )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 423
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 424
def rest_path ( self ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 425
"""returns a REST-like (relative) path for this entity"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 426
mainattr , needcheck = self . _rest_attr_info ()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 427
etype = str ( self . e_schema )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 428
if mainattr == 'eid' :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 429
value = self . eid
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 430
else :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 431
value = getattr ( self , mainattr )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 432
if value is None :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 433
return ' %s /eid/ %s ' % ( etype . lower (), self . eid )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 434
if needcheck :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 435
# make sure url is not ambiguous
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 436
rql = 'Any COUNT(X) WHERE X is %s , X %s %% (value)s' % ( etype , mainattr )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 437
if value is not None :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 438
nbresults = self . req . execute ( rql , { 'value' : value })[ 0 ][ 0 ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 439
# may an assertion that nbresults is not 0 would be a good idea
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 440
if nbresults != 1 : # no ambiguity
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 441
return ' %s /eid/ %s ' % ( etype . lower (), self . eid )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 442
return ' %s / %s ' % ( etype . lower (), self . req . url_quote ( value ))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 443
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 444
@classmethod
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 445
def _rest_attr_info ( cls ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 446
mainattr , needcheck = 'eid' , True
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 447
if cls . rest_attr :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 448
mainattr = cls . rest_attr
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 449
needcheck = not cls . e_schema . has_unique_values ( mainattr )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 450
else :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 451
for rschema in cls . e_schema . subject_relations ():
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 452
if rschema . is_final () and rschema != 'eid' and cls . e_schema . has_unique_values ( rschema ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 453
mainattr = str ( rschema )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 454
needcheck = False
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 455
break
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 456
if mainattr == 'eid' :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 457
needcheck = False
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 458
return mainattr , needcheck
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 459
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 460
@cached
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 461
def formatted_attrs ( self ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 462
"""returns the list of attributes which have some format information
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 463
(i.e. rich text strings)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 464
"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 465
attrs = []
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 466
for rschema , attrschema in self . e_schema . attribute_definitions ():
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 467
if attrschema . type == 'String' and self . has_format ( rschema ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 468
attrs . append ( rschema . type )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 469
return attrs
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 470
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 471
def format ( self , attr ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 472
"""return the mime type format for an attribute (if specified)"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 473
return getattr ( self , ' %s _format' % attr , None )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 474
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 475
def text_encoding ( self , attr ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 476
"""return the text encoding for an attribute, default to site encoding
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 477
"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 478
encoding = getattr ( self , ' %s _encoding' % attr , None )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 479
return encoding or self . vreg . property_value ( 'ui.encoding' )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 480
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 481
def has_format ( self , attr ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 482
"""return true if this entity's schema has a format field for the given
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 483
attribute
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 484
"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 485
return self . e_schema . has_subject_relation ( ' %s _format' % attr )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 486
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 487
def has_text_encoding ( self , attr ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 488
"""return true if this entity's schema has ab encoding field for the
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 489
given attribute
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 490
"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 491
return self . e_schema . has_subject_relation ( ' %s _encoding' % attr )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 492
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 493
def printable_value ( self , attr , value = _marker , attrtype = None ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 494
format = 'text/html' , displaytime = True ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 495
"""return a displayable value (i.e. unicode string) which may contains
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 496
html tags
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 497
"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 498
attr = str ( attr )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 499
if value is _marker :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 500
value = getattr ( self , attr )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 501
if isinstance ( value , basestring ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 502
value = value . strip ()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 503
if value is None or value == '' : # don't use "not", 0 is an acceptable value
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 504
return u ''
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 505
if attrtype is None :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 506
attrtype = self . e_schema . destination ( attr )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 507
props = self . e_schema . rproperties ( attr )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 508
if attrtype == 'String' :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 509
# internalinalized *and* formatted string such as schema
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 510
# description...
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 511
if props . get ( 'internationalizable' ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 512
value = self . req . _ ( value )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 513
attrformat = self . format ( attr )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 514
if attrformat :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 515
return self . mtc_transform ( value , attrformat , format ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 516
self . req . encoding )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 517
elif attrtype == 'Bytes' :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 518
attrformat = self . format ( attr )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 519
if attrformat :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 520
try :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 521
encoding = getattr ( self , ' %s _encoding' % attr )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 522
except AttributeError :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 523
encoding = self . req . encoding
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 524
return self . mtc_transform ( value . getvalue (), attrformat , format ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 525
encoding )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 526
return u ''
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 527
value = printable_value ( self . req , attrtype , value , props , displaytime )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 528
if format == 'text/html' :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 529
value = html_escape ( value )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 530
return value
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 531
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 532
def mtc_transform ( self , data , format , target_format , encoding ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 533
_engine = ENGINE ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 534
trdata = TransformData ( data , format , encoding , appobject = self )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 535
data = _engine . convert ( trdata , target_format ) . decode ()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 536
if format == 'text/html' :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 537
data = soup2xhtml ( data , self . req . encoding )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 538
return data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 539
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 540
# entity cloning ##########################################################
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 541
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 542
def copy_relations ( self , ceid ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 543
"""copy relations of the object with the given eid on this object
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 544
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 545
By default meta and composite relations are skipped.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 546
Overrides this if you want another behaviour
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 547
"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 548
assert self . has_eid ()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 549
execute = self . req . execute
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 550
for rschema in self . e_schema . subject_relations ():
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 551
if rschema . meta or rschema . is_final ():
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 552
continue
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 553
# skip already defined relations
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 554
if getattr ( self , rschema . type ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 555
continue
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 556
if rschema . type in self . skip_copy_for :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 557
continue
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 558
if rschema . type == 'in_state' :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 559
# if the workflow is defining an initial state (XXX AND we are
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 560
# not in the managers group? not done to be more consistent)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 561
# don't try to copy in_state
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 562
if execute ( 'Any S WHERE S state_of ET, ET initial_state S,'
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 563
'ET name %(etype)s ' , { 'etype' : str ( self . e_schema )}):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 564
continue
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 565
# skip composite relation
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 566
if self . e_schema . subjrproperty ( rschema , 'composite' ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 567
continue
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 568
# skip relation with card in ?1 else we either change the copied
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 569
# object (inlined relation) or inserting some inconsistency
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 570
if self . e_schema . subjrproperty ( rschema , 'cardinality' )[ 1 ] in '?1' :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 571
continue
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 572
rql = 'SET X %s V WHERE X eid %% (x)s, Y eid %% (y)s, Y %s V' % (
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 573
rschema . type , rschema . type )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 574
execute ( rql , { 'x' : self . eid , 'y' : ceid }, ( 'x' , 'y' ))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 575
self . clear_related_cache ( rschema . type , 'subject' )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 576
for rschema in self . e_schema . object_relations ():
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 577
if rschema . meta :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 578
continue
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 579
# skip already defined relations
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 580
if getattr ( self , 'reverse_ %s ' % rschema . type ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 581
continue
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 582
# skip composite relation
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 583
if self . e_schema . objrproperty ( rschema , 'composite' ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 584
continue
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 585
# skip relation with card in ?1 else we either change the copied
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 586
# object (inlined relation) or inserting some inconsistency
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 587
if self . e_schema . objrproperty ( rschema , 'cardinality' )[ 0 ] in '?1' :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 588
continue
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 589
rql = 'SET V %s X WHERE X eid %% (x)s, Y eid %% (y)s, V %s Y' % (
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 590
rschema . type , rschema . type )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 591
execute ( rql , { 'x' : self . eid , 'y' : ceid }, ( 'x' , 'y' ))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 592
self . clear_related_cache ( rschema . type , 'object' )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 593
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 594
# data fetching methods ###################################################
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 595
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 596
@cached
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 597
def as_rset ( self ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 598
"""returns a resultset containing `self` information"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 599
rset = ResultSet ([( self . eid ,)], 'Any X WHERE X eid %(x)s ' ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 600
{ 'x' : self . eid }, [( self . id ,)])
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 601
return self . req . decorate_rset ( rset )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 602
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 603
def to_complete_relations ( self ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 604
"""by default complete final relations to when calling .complete()"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 605
for rschema in self . e_schema . subject_relations ():
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 606
if rschema . is_final ():
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 607
continue
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 608
if len ( rschema . objects ( self . e_schema )) > 1 :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 609
# ambigous relations, the querier doesn't handle
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 610
# outer join correctly in this case
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 611
continue
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 612
if rschema . inlined :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 613
matching_groups = self . req . user . matching_groups
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 614
if matching_groups ( rschema . get_groups ( 'read' )) and \
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 615
all ( matching_groups ( es . get_groups ( 'read' ))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 616
for es in rschema . objects ( self . e_schema )):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 617
yield rschema , 'subject'
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 618
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 619
def to_complete_attributes ( self , skip_bytes = True ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 620
for rschema , attrschema in self . e_schema . attribute_definitions ():
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 621
# skip binary data by default
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 622
if skip_bytes and attrschema . type == 'Bytes' :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 623
continue
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 624
attr = rschema . type
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 625
if attr == 'eid' :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 626
continue
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 627
# password retreival is blocked at the repository server level
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 628
if not self . req . user . matching_groups ( rschema . get_groups ( 'read' )) \
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 629
or attrschema . type == 'Password' :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 630
self [ attr ] = None
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 631
continue
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 632
yield attr
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 633
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 634
def complete ( self , attributes = None , skip_bytes = True ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 635
"""complete this entity by adding missing attributes (i.e. query the
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 636
repository to fill the entity)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 637
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 638
:type skip_bytes: bool
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 639
:param skip_bytes:
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 640
if true, attribute of type Bytes won't be considered
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 641
"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 642
assert self . has_eid ()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 643
varmaker = rqlvar_maker ()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 644
V = varmaker . next ()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 645
rql = [ 'WHERE %s eid %% (x)s' % V ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 646
selected = []
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 647
for attr in ( attributes or self . to_complete_attributes ( skip_bytes )):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 648
# if attribute already in entity, nothing to do
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 649
if self . has_key ( attr ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 650
continue
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 651
# case where attribute must be completed, but is not yet in entity
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 652
var = varmaker . next ()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 653
rql . append ( ' %s %s %s ' % ( V , attr , var ))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 654
selected . append (( attr , var ))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 655
# +1 since this doen't include the main variable
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 656
lastattr = len ( selected ) + 1
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 657
if attributes is None :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 658
# fetch additional relations (restricted to 0..1 relations)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 659
for rschema , role in self . to_complete_relations ():
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 660
rtype = rschema . type
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 661
if self . relation_cached ( rtype , role ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 662
continue
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 663
var = varmaker . next ()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 664
if role == 'subject' :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 665
targettype = rschema . objects ( self . e_schema )[ 0 ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 666
card = rschema . rproperty ( self . e_schema , targettype ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 667
'cardinality' )[ 0 ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 668
if card == '1' :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 669
rql . append ( ' %s %s %s ' % ( V , rtype , var ))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 670
else : # '?"
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 671
rql . append ( ' %s %s %s ?' % ( V , rtype , var ))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 672
else :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 673
targettype = rschema . subjects ( self . e_schema )[ 1 ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 674
card = rschema . rproperty ( self . e_schema , targettype ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 675
'cardinality' )[ 1 ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 676
if card == '1' :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 677
rql . append ( ' %s %s %s ' % ( var , rtype , V ))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 678
else : # '?"
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 679
rql . append ( ' %s ? %s %s ' % ( var , rtype , V ))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 680
assert card in '1?' , ' %s %s %s %s ' % ( self . e_schema , rtype ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 681
role , card )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 682
selected . append ((( rtype , role ), var ))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 683
if selected :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 684
# select V, we need it as the left most selected variable
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 685
# if some outer join are included to fetch inlined relations
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 686
rql = 'Any %s , %s %s ' % ( V , ',' . join ( var for attr , var in selected ),
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 687
',' . join ( rql ))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 688
execute = getattr ( self . req , 'unsafe_execute' , self . req . execute )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 689
rset = execute ( rql , { 'x' : self . eid }, 'x' , build_descr = False )[ 0 ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 690
# handle attributes
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 691
for i in xrange ( 1 , lastattr ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 692
self [ str ( selected [ i - 1 ][ 0 ])] = rset [ i ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 693
# handle relations
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 694
for i in xrange ( lastattr , len ( rset )):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 695
rtype , x = selected [ i - 1 ][ 0 ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 696
value = rset [ i ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 697
if value is None :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 698
rrset = ResultSet ([], rql , { 'x' : self . eid })
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 699
self . req . decorate_rset ( rrset )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 700
else :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 701
rrset = self . req . eid_rset ( value )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 702
self . set_related_cache ( rtype , x , rrset )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 703
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 704
def get_value ( self , name ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 705
"""get value for the attribute relation <name>, query the repository
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 706
to get the value if necessary.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 707
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 708
:type name: str
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 709
:param name: name of the attribute to get
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 710
"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 711
try :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 712
value = self [ name ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 713
except KeyError :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 714
if not self . is_saved ():
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 715
return None
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 716
rql = "Any A WHERE X eid %% (x)s, X %s A" % name
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 717
# XXX should we really use unsafe_execute here??
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 718
execute = getattr ( self . req , 'unsafe_execute' , self . req . execute )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 719
try :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 720
rset = execute ( rql , { 'x' : self . eid }, 'x' )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 721
except Unauthorized :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 722
self [ name ] = value = None
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 723
else :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 724
assert rset . rowcount <= 1 , ( self , rql , rset . rowcount )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 725
try :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 726
self [ name ] = value = rset . rows [ 0 ][ 0 ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 727
except IndexError :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 728
# probably a multisource error
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 729
self . critical ( "can't get value for attribute %s of entity with eid %s " ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 730
name , self . eid )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 731
if self . e_schema . destination ( name ) == 'String' :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 732
self [ name ] = value = self . req . _ ( 'unaccessible' )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 733
else :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 734
self [ name ] = value = None
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 735
return value
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 736
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 737
def related ( self , rtype , role = 'subject' , limit = None , entities = False ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 738
"""returns a resultset of related entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 739
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 740
:param role: is the role played by 'self' in the relation ('subject' or 'object')
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 741
:param limit: resultset's maximum size
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 742
:param entities: if True, the entites are returned; if False, a result set is returned
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 743
"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 744
try :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 745
return self . related_cache ( rtype , role , entities , limit )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 746
except KeyError :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 747
pass
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 748
assert self . has_eid ()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 749
rql = self . related_rql ( rtype , role )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 750
rset = self . req . execute ( rql , { 'x' : self . eid }, 'x' )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 751
self . set_related_cache ( rtype , role , rset )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 752
return self . related ( rtype , role , limit , entities )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 753
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 754
def related_rql ( self , rtype , role = 'subject' ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 755
rschema = self . schema [ rtype ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 756
if role == 'subject' :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 757
targettypes = rschema . objects ( self . e_schema )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 758
restriction = 'E eid %% (x)s, E %s X' % rtype
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 759
card = greater_card ( rschema , ( self . e_schema ,), targettypes , 0 )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 760
else :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 761
targettypes = rschema . subjects ( self . e_schema )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 762
restriction = 'E eid %% (x)s, X %s E' % rtype
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 763
card = greater_card ( rschema , targettypes , ( self . e_schema ,), 1 )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 764
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>
diff
changeset
+ − 765
fetchattrs_list = []
0
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 766
for ttype in targettypes :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 767
etypecls = self . vreg . 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>
diff
changeset
+ − 768
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>
diff
changeset
+ − 769
fetchattrs = reduce ( set . intersection , fetchattrs_list )
0
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 770
rql = etypecls . fetch_rql ( self . req . user , [ restriction ], fetchattrs ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 771
settype = False )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 772
else :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 773
etypecls = self . vreg . etype_class ( targettypes [ 0 ])
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 774
rql = etypecls . fetch_rql ( self . req . user , [ restriction ], settype = False )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 775
# optimisation: remove ORDERBY if cardinality is 1 or ? (though
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 776
# greater_card return 1 for those both cases)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 777
if card == '1' :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 778
if ' ORDERBY ' in rql :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 779
rql = ' %s WHERE %s ' % ( rql . split ( ' ORDERBY ' , 1 )[ 0 ],
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 780
rql . split ( ' WHERE ' , 1 )[ 1 ])
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 781
elif not ' ORDERBY ' in rql :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 782
args = tuple ( rql . split ( ' WHERE ' , 1 ))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 783
rql = ' %s ORDERBY Z DESC WHERE X modification_date Z, %s ' % args
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 784
return rql
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 785
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 786
# generic vocabulary methods ##############################################
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 787
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 788
def vocabulary ( self , rtype , role = 'subject' , limit = None ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 789
"""vocabulary functions must return a list of couples
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 790
(label, eid) that will typically be used to fill the
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 791
edition view's combobox.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 792
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 793
If `eid` is None in one of these couples, it should be
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 794
interpreted as a separator in case vocabulary results are grouped
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 795
"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 796
try :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 797
vocabfunc = getattr ( self , ' %s _ %s _vocabulary' % ( role , rtype ))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 798
except AttributeError :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 799
vocabfunc = getattr ( self , ' %s _relation_vocabulary' % role )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 800
# NOTE: it is the responsibility of `vocabfunc` to sort the result
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 801
# (direclty through RQL or via a python sort). This is also
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 802
# important because `vocabfunc` might return a list with
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 803
# couples (label, None) which act as separators. In these
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 804
# cases, it doesn't make sense to sort results afterwards.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 805
return vocabfunc ( rtype , limit )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 806
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 807
def subject_relation_vocabulary ( self , rtype , limit = None ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 808
"""defaut vocabulary method for the given relation, looking for
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 809
relation's object entities (i.e. self is the subject)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 810
"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 811
if isinstance ( rtype , basestring ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 812
rtype = self . schema . rschema ( rtype )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 813
done = None
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 814
assert not rtype . is_final (), rtype
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 815
if self . has_eid ():
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 816
done = set ( e . eid for e in getattr ( self , str ( rtype )))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 817
result = []
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 818
rsetsize = None
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 819
for objtype in rtype . objects ( self . e_schema ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 820
if limit is not None :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 821
rsetsize = limit - len ( result )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 822
result += self . relation_vocabulary ( rtype , objtype , 'subject' ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 823
rsetsize , done )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 824
if limit is not None and len ( result ) >= limit :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 825
break
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 826
return result
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 827
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 828
def object_relation_vocabulary ( self , rtype , limit = None ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 829
"""defaut vocabulary method for the given relation, looking for
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 830
relation's subject entities (i.e. self is the object)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 831
"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 832
if isinstance ( rtype , basestring ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 833
rtype = self . schema . rschema ( rtype )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 834
done = None
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 835
if self . has_eid ():
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 836
done = set ( e . eid for e in getattr ( self , 'reverse_ %s ' % rtype ))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 837
result = []
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 838
rsetsize = None
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 839
for subjtype in rtype . subjects ( self . e_schema ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 840
if limit is not None :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 841
rsetsize = limit - len ( result )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 842
result += self . relation_vocabulary ( rtype , subjtype , 'object' ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 843
rsetsize , done )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 844
if limit is not None and len ( result ) >= limit :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 845
break
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 846
return result
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 847
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 848
def relation_vocabulary ( self , rtype , targettype , role ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 849
limit = None , done = None ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 850
if done is None :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 851
done = set ()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 852
req = self . req
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 853
rset = self . unrelated ( rtype , targettype , role , limit )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 854
res = []
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 855
for entity in rset . entities ():
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 856
if entity . eid in done :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 857
continue
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 858
done . add ( entity . eid )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 859
res . append (( entity . view ( 'combobox' ), entity . eid ))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 860
return res
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 861
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 862
def unrelated_rql ( self , rtype , targettype , role , ordermethod = None ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 863
vocabconstraints = True ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 864
"""build a rql to fetch `targettype` entities unrelated to this entity
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 865
using (rtype, role) relation
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 866
"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 867
ordermethod = ordermethod or 'fetch_unrelated_order'
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 868
if isinstance ( rtype , basestring ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 869
rtype = self . schema . rschema ( rtype )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 870
if role == 'subject' :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 871
evar , searchedvar = 'S' , 'O'
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 872
subjtype , objtype = self . e_schema , targettype
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 873
else :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 874
searchedvar , evar = 'S' , 'O'
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 875
objtype , subjtype = self . e_schema , targettype
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 876
if self . has_eid ():
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 877
restriction = [ 'NOT S %s O' % rtype , ' %s eid %% (x)s' % evar ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 878
else :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 879
restriction = []
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 880
constraints = rtype . rproperty ( subjtype , objtype , 'constraints' )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 881
if vocabconstraints :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 882
# RQLConstraint is a subclass for RQLVocabularyConstraint, so they
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 883
# will be included as well
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 884
restriction += [ cstr . restriction for cstr in constraints
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 885
if isinstance ( cstr , RQLVocabularyConstraint )]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 886
else :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 887
restriction += [ cstr . restriction for cstr in constraints
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 888
if isinstance ( cstr , RQLConstraint )]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 889
etypecls = self . vreg . etype_class ( targettype )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 890
rql = etypecls . fetch_rql ( self . req . user , restriction ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 891
mainvar = searchedvar , ordermethod = ordermethod )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 892
# ensure we have an order defined
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 893
if not ' ORDERBY ' in rql :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 894
before , after = rql . split ( ' WHERE ' , 1 )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 895
rql = ' %s ORDERBY %s WHERE %s ' % ( before , searchedvar , after )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 896
return rql
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 897
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 898
def unrelated ( self , rtype , targettype , role = 'subject' , limit = None ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 899
ordermethod = None ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 900
"""return a result set of target type objects that may be related
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 901
by a given relation, with self as subject or object
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 902
"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 903
rql = self . unrelated_rql ( rtype , targettype , role , ordermethod )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 904
if limit is not None :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 905
before , after = rql . split ( ' WHERE ' , 1 )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 906
rql = ' %s LIMIT %s WHERE %s ' % ( before , limit , after )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 907
if self . has_eid ():
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 908
return self . req . execute ( rql , { 'x' : self . eid })
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 909
return self . req . execute ( rql )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 910
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 911
# relations cache handling ################################################
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 912
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 913
def relation_cached ( self , rtype , role ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 914
"""return true if the given relation is already cached on the instance
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 915
"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 916
return ' %s _ %s ' % ( rtype , role ) in self . _related_cache
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 917
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 918
def related_cache ( self , rtype , role , entities = True , limit = None ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 919
"""return values for the given relation if it's cached on the instance,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 920
else raise `KeyError`
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 921
"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 922
res = self . _related_cache [ ' %s _ %s ' % ( rtype , role )][ entities ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 923
if limit :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 924
if entities :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 925
res = res [: limit ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 926
else :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 927
res = res . limit ( limit )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 928
return res
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 929
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 930
def set_related_cache ( self , rtype , role , rset , col = 0 ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 931
"""set cached values for the given relation"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 932
if rset :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 933
related = list ( rset . entities ( col ))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 934
rschema = self . schema . rschema ( rtype )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 935
if role == 'subject' :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 936
rcard = rschema . rproperty ( self . e_schema , related [ 0 ] . e_schema ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 937
'cardinality' )[ 1 ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 938
target = 'object'
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 939
else :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 940
rcard = rschema . rproperty ( related [ 0 ] . e_schema , self . e_schema ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 941
'cardinality' )[ 0 ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 942
target = 'subject'
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 943
if rcard in '?1' :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 944
for rentity in related :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 945
rentity . _related_cache [ ' %s _ %s ' % ( rtype , target )] = ( self . as_rset (), [ self ])
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 946
else :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 947
related = []
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 948
self . _related_cache [ ' %s _ %s ' % ( rtype , role )] = ( rset , related )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 949
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 950
def clear_related_cache ( self , rtype = None , role = None ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 951
"""clear cached values for the given relation or the entire cache if
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 952
no relation is given
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 953
"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 954
if rtype is None :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 955
self . _related_cache = {}
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 956
else :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 957
assert role
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 958
self . _related_cache . pop ( ' %s _ %s ' % ( rtype , role ), None )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 959
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 960
# raw edition utilities ###################################################
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 961
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 962
def set_attributes ( self , ** kwargs ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 963
assert kwargs
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 964
relations = []
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 965
for key in kwargs :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 966
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>
diff
changeset
+ − 967
# update current local object
cf577e26f924
don't introduce a spurious 'x' key in the entity-as dict
Aurelien Campeas <aurelien.campeas@logilab.fr>
diff
changeset
+ − 968
self . update ( kwargs )
cf577e26f924
don't introduce a spurious 'x' key in the entity-as dict
Aurelien Campeas <aurelien.campeas@logilab.fr>
diff
changeset
+ − 969
# and now update the database
0
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 970
kwargs [ 'x' ] = self . eid
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 971
self . req . execute ( 'SET %s WHERE X eid %% (x)s' % ',' . join ( relations ),
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 972
kwargs , 'x' )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 973
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 974
def delete ( self ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 975
assert self . has_eid (), self . eid
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 976
self . req . execute ( 'DELETE %s X WHERE X eid %% (x)s' % self . e_schema ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 977
{ 'x' : self . eid })
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 978
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 979
# server side utilities ###################################################
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 980
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 981
def set_defaults ( self ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 982
"""set default values according to the schema"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 983
self . _default_set = set ()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 984
for attr , value in self . e_schema . defaults ():
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 985
if not self . has_key ( attr ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 986
self [ str ( attr )] = value
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 987
self . _default_set . add ( attr )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 988
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 989
def check ( self , creation = False ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 990
"""check this entity against its schema. Only final relation
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 991
are checked here, constraint on actual relations are checked in hooks
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 992
"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 993
# necessary since eid is handled specifically and yams require it to be
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 994
# in the dictionary
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 995
if self . req is None :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 996
_ = unicode
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 997
else :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 998
_ = self . req . _
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 999
self . e_schema . check ( self , creation = creation , _ = _ )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1000
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1001
def fti_containers ( self , _done = None ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1002
if _done is None :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1003
_done = set ()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1004
_done . add ( self . eid )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1005
containers = tuple ( self . e_schema . fulltext_containers ())
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1006
if containers :
476
+ − 1007
yielded = False
0
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1008
for rschema , target in containers :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1009
if target == 'object' :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1010
targets = getattr ( self , rschema . type )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1011
else :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1012
targets = getattr ( self , 'reverse_ %s ' % rschema )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1013
for entity in targets :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1014
if entity . eid in _done :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1015
continue
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1016
for container in entity . fti_containers ( _done ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1017
yield container
476
+ − 1018
yielded = True
+ − 1019
if not yielded :
+ − 1020
yield self
0
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1021
else :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1022
yield self
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1023
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1024
def get_words ( self ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1025
"""used by the full text indexer to get words to index
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1026
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1027
this method should only be used on the repository side since it depends
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1028
on the indexer package
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1029
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1030
:rtype: list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1031
:return: the list of indexable word of this entity
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1032
"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1033
from indexer.query_objects import tokenize
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1034
words = []
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1035
for rschema in self . e_schema . indexable_attributes ():
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1036
try :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1037
value = self . printable_value ( rschema , format = 'text/plain' )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1038
except TransformError , ex :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1039
continue
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1040
except :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1041
self . exception ( "can't add value of %s to text index for entity %s " ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1042
rschema , self . eid )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1043
continue
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1044
if value :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1045
words += tokenize ( value )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1046
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1047
for rschema , role in self . e_schema . fulltext_relations ():
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1048
if role == 'subject' :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1049
for entity in getattr ( self , rschema . type ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1050
words += entity . get_words ()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1051
else : # if role == 'object':
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1052
for entity in getattr ( self , 'reverse_ %s ' % rschema . type ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1053
words += entity . get_words ()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1054
return words
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1055
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1056
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1057
# attribute and relation descriptors ##########################################
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1058
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1059
class Attribute ( object ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1060
"""descriptor that controls schema attribute access"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1061
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1062
def __init__ ( self , attrname ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1063
assert attrname != 'eid'
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1064
self . _attrname = attrname
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1065
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1066
def __get__ ( self , eobj , eclass ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1067
if eobj is None :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1068
return self
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1069
return eobj . get_value ( self . _attrname )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1070
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1071
def __set__ ( self , eobj , value ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1072
# XXX bw compat
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1073
# would be better to generate UPDATE queries than the current behaviour
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1074
eobj . warning ( "deprecated usage, don't use 'entity.attr = val' notation)" )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1075
eobj [ self . _attrname ] = value
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1076
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1077
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1078
class Relation ( object ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1079
"""descriptor that controls schema relation access"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1080
_role = None # for pylint
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1081
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1082
def __init__ ( self , rschema ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1083
self . _rschema = rschema
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1084
self . _rtype = rschema . type
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1085
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1086
def __get__ ( self , eobj , eclass ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1087
if eobj is None :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1088
raise AttributeError ( ' %s cannot be only be accessed from instances'
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1089
% self . _rtype )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1090
return eobj . related ( self . _rtype , self . _role , entities = True )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1091
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1092
def __set__ ( self , eobj , value ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1093
raise NotImplementedError
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1094
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1095
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1096
class SubjectRelation ( Relation ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1097
"""descriptor that controls schema relation access"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1098
_role = 'subject'
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1099
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1100
class ObjectRelation ( Relation ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1101
"""descriptor that controls schema relation access"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1102
_role = 'object'
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1103
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1104
from logging import getLogger
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1105
from cubicweb import set_log_methods
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1106
set_log_methods ( Entity , getLogger ( 'cubicweb.entity' ))