entity.py
changeset 10354 635cfac73d28
parent 10041 504c4eacbfd8
child 10357 59a79300f213
equal deleted inserted replaced
10353:d9a1e7939ee6 10354:635cfac73d28
   512 
   512 
   513         You can also set relations where the entity has 'object' role by
   513         You can also set relations where the entity has 'object' role by
   514         prefixing the relation name by 'reverse_'. Also, relation values may be
   514         prefixing the relation name by 'reverse_'. Also, relation values may be
   515         an entity or eid, a list of entities or eids.
   515         an entity or eid, a list of entities or eids.
   516         """
   516         """
   517         rql, qargs, pendingrels, attrcache = cls._cw_build_entity_query(kwargs)
   517         rql, qargs, pendingrels, _attrcache = cls._cw_build_entity_query(kwargs)
   518         if rql:
   518         if rql:
   519             rql = 'INSERT %s X: %s' % (cls.__regid__, rql)
   519             rql = 'INSERT %s X: %s' % (cls.__regid__, rql)
   520         else:
   520         else:
   521             rql = 'INSERT %s X' % (cls.__regid__)
   521             rql = 'INSERT %s X' % (cls.__regid__)
   522         try:
   522         try:
   523             created = execute(rql, qargs).get_entity(0, 0)
   523             created = execute(rql, qargs).get_entity(0, 0)
   524         except IndexError:
   524         except IndexError:
   525             raise Exception('could not create a %r with %r (%r)' %
   525             raise Exception('could not create a %r with %r (%r)' %
   526                             (cls.__regid__, rql, qargs))
   526                             (cls.__regid__, rql, qargs))
   527         created._cw_update_attr_cache(attrcache)
       
   528         cls._cw_handle_pending_relations(created.eid, pendingrels, execute)
   527         cls._cw_handle_pending_relations(created.eid, pendingrels, execute)
   529         return created
   528         return created
   530 
   529 
   531     def __init__(self, req, rset=None, row=None, col=0):
   530     def __init__(self, req, rset=None, row=None, col=0):
   532         AppObject.__init__(self, req, rset=rset, row=row, col=col)
   531         AppObject.__init__(self, req, rset=rset, row=row, col=col)
   554         if isinstance(self.eid, (int, long)):
   553         if isinstance(self.eid, (int, long)):
   555             return self.eid
   554             return self.eid
   556         return super(Entity, self).__hash__()
   555         return super(Entity, self).__hash__()
   557 
   556 
   558     def _cw_update_attr_cache(self, attrcache):
   557     def _cw_update_attr_cache(self, attrcache):
   559         # if context is a repository session, don't consider dont-cache-attrs as
       
   560         # the instance already holds modified values and loosing them could
       
   561         # introduce severe problems
       
   562         trdata = self._cw.transaction_data
   558         trdata = self._cw.transaction_data
   563         uncached_attrs = trdata.get('%s.storage-special-process-attrs' % self.eid, set())
   559         uncached_attrs = trdata.get('%s.storage-special-process-attrs' % self.eid, set())
   564         if self._cw.is_request:
       
   565             uncached_attrs.update(trdata.get('%s.dont-cache-attrs' % self.eid, set()))
       
   566         for attr in uncached_attrs:
   560         for attr in uncached_attrs:
   567             attrcache.pop(attr, None)
   561             attrcache.pop(attr, None)
   568             self.cw_attr_cache.pop(attr, None)
   562             self.cw_attr_cache.pop(attr, None)
   569         self.cw_attr_cache.update(attrcache)
   563         self.cw_attr_cache.update(attrcache)
   570 
   564 
   571     def _cw_dont_cache_attribute(self, attr, repo_side=False):
   565     def _cw_dont_cache_attribute(self, attr, repo_side=False):
   572         """Repository side method called when some attribute has been
   566         """Called when some attribute has been transformed by a *storage*,
   573         transformed by a hook, hence original value should not be cached by
   567         hence the original value should not be cached **by anyone**.
   574         the client.
       
   575 
       
   576         If repo_side is True, this means that the attribute has been
       
   577         transformed by a *storage*, hence the original value should
       
   578         not be cached **by anyone**.
       
   579 
       
   580         This only applies to a storage special case where the value
       
   581         specified in creation or update is **not** the value that will
       
   582         be transparently exposed later.
       
   583 
   568 
   584         For example we have a special "fs_importing" mode in BFSS
   569         For example we have a special "fs_importing" mode in BFSS
   585         where a file path is given as attribute value and stored as is
   570         where a file path is given as attribute value and stored as is
   586         in the data base. Later access to the attribute will provide
   571         in the data base. Later access to the attribute will provide
   587         the content of the file at the specified path. We do not want
   572         the content of the file at the specified path. We do not want
   588         the "filepath" value to be cached.
   573         the "filepath" value to be cached.
   589         """
   574 
   590         self._cw.transaction_data.setdefault('%s.dont-cache-attrs' % self.eid, set()).add(attr)
   575         """
   591         if repo_side:
   576         trdata = self._cw.transaction_data
   592             trdata = self._cw.transaction_data
   577         trdata.setdefault('%s.storage-special-process-attrs' % self.eid, set()).add(attr)
   593             trdata.setdefault('%s.storage-special-process-attrs' % self.eid, set()).add(attr)
       
   594 
   578 
   595     def __json_encode__(self):
   579     def __json_encode__(self):
   596         """custom json dumps hook to dump the entity's eid
   580         """custom json dumps hook to dump the entity's eid
   597         which is not part of dict structure itself
   581         which is not part of dict structure itself
   598         """
   582         """
   834             execute(rql, {'x': self.eid, 'y': ceid})
   818             execute(rql, {'x': self.eid, 'y': ceid})
   835             self.cw_clear_relation_cache(rschema.type, 'object')
   819             self.cw_clear_relation_cache(rschema.type, 'object')
   836 
   820 
   837     # data fetching methods ###################################################
   821     # data fetching methods ###################################################
   838 
   822 
   839     @cached
       
   840     def as_rset(self): # XXX .cw_as_rset
   823     def as_rset(self): # XXX .cw_as_rset
   841         """returns a resultset containing `self` information"""
   824         """returns a resultset containing `self` information"""
   842         rset = ResultSet([(self.eid,)], 'Any X WHERE X eid %(x)s',
   825         rset = ResultSet([(self.eid,)], 'Any X WHERE X eid %(x)s',
   843                          {'x': self.eid}, [(self.cw_etype,)])
   826                          {'x': self.eid}, [(self.cw_etype,)])
   844         rset.req = self._cw
   827         rset.req = self._cw
  1327             if ' WHERE ' in rql:
  1310             if ' WHERE ' in rql:
  1328                 rql += ', X eid %(x)s'
  1311                 rql += ', X eid %(x)s'
  1329             else:
  1312             else:
  1330                 rql += ' WHERE X eid %(x)s'
  1313                 rql += ' WHERE X eid %(x)s'
  1331             self._cw.execute(rql, qargs)
  1314             self._cw.execute(rql, qargs)
  1332         # update current local object _after_ the rql query to avoid
       
  1333         # interferences between the query execution itself and the cw_edited /
       
  1334         # skip_security machinery
       
  1335         self._cw_update_attr_cache(attrcache)
       
  1336         self._cw_handle_pending_relations(self.eid, pendingrels, self._cw.execute)
  1315         self._cw_handle_pending_relations(self.eid, pendingrels, self._cw.execute)
  1337         # XXX update relation cache
  1316         # XXX update relation cache
  1338 
  1317 
  1339     def cw_delete(self, **kwargs):
  1318     def cw_delete(self, **kwargs):
  1340         assert self.has_eid(), self.eid
  1319         assert self.has_eid(), self.eid