cubicweb/server/session.py
changeset 12029 3d9883a6068f
parent 12028 08c866d2f11d
child 12033 1ce12b716e71
equal deleted inserted replaced
12028:08c866d2f11d 12029:3d9883a6068f
    27 from logging import getLogger
    27 from logging import getLogger
    28 
    28 
    29 from six import text_type
    29 from six import text_type
    30 
    30 
    31 from logilab.common.deprecation import deprecated
    31 from logilab.common.deprecation import deprecated
    32 from logilab.common.textutils import unormalize
       
    33 from logilab.common.registry import objectify_predicate
    32 from logilab.common.registry import objectify_predicate
    34 
    33 
    35 from cubicweb import QueryError, ProgrammingError, schema, server
    34 from cubicweb import QueryError, ProgrammingError, schema, server
    36 from cubicweb import set_log_methods
    35 from cubicweb import set_log_methods
    37 from cubicweb.req import RequestSessionBase
    36 from cubicweb.req import RequestSessionBase
    38 from cubicweb.utils import make_uid
       
    39 from cubicweb.rqlrewrite import RQLRewriter
    37 from cubicweb.rqlrewrite import RQLRewriter
    40 from cubicweb.server.edition import EditedEntity
    38 from cubicweb.server.edition import EditedEntity
    41 
    39 
    42 
    40 
    43 NO_UNDO_TYPES = schema.SCHEMA_TYPES.copy()
    41 NO_UNDO_TYPES = schema.SCHEMA_TYPES.copy()
   174 def _open_only(func):
   172 def _open_only(func):
   175     """decorator for Connection method that check it is open"""
   173     """decorator for Connection method that check it is open"""
   176     @functools.wraps(func)
   174     @functools.wraps(func)
   177     def check_open(cnx, *args, **kwargs):
   175     def check_open(cnx, *args, **kwargs):
   178         if not cnx._open:
   176         if not cnx._open:
   179             raise ProgrammingError('Closed Connection: %s'
   177             raise ProgrammingError('Closed Connection: %s' % cnx)
   180                                    % cnx.connectionid)
       
   181         return func(cnx, *args, **kwargs)
   178         return func(cnx, *args, **kwargs)
   182     return check_open
   179     return check_open
   183 
   180 
   184 
   181 
   185 class Connection(RequestSessionBase):
   182 class Connection(RequestSessionBase):
   245 
   242 
   246     def __init__(self, session):
   243     def __init__(self, session):
   247         super(Connection, self).__init__(session.repo.vreg)
   244         super(Connection, self).__init__(session.repo.vreg)
   248         #: connection unique id
   245         #: connection unique id
   249         self._open = None
   246         self._open = None
   250         self.connectionid = '%s-%s' % (session.sessionid, uuid4().hex)
       
   251         self.session = session
   247         self.session = session
   252         self.sessionid = session.sessionid
       
   253 
   248 
   254         #: server.Repository object
   249         #: server.Repository object
   255         self.repo = session.repo
   250         self.repo = session.repo
   256         self.vreg = self.repo.vreg
   251         self.vreg = self.repo.vreg
   257         self._execute = self.repo.querier.execute
   252         self._execute = self.repo.querier.execute
   476     def set_entity_cache(self, entity):
   471     def set_entity_cache(self, entity):
   477         """Add `entity` to the connection entity cache"""
   472         """Add `entity` to the connection entity cache"""
   478         # XXX not using _open_only because before at creation time. _set_user
   473         # XXX not using _open_only because before at creation time. _set_user
   479         # call this function to cache the Connection user.
   474         # call this function to cache the Connection user.
   480         if entity.cw_etype != 'CWUser' and not self._open:
   475         if entity.cw_etype != 'CWUser' and not self._open:
   481             raise ProgrammingError('Closed Connection: %s' % self.connectionid)
   476             raise ProgrammingError('Closed Connection: %s' % self)
   482         ecache = self.transaction_data.setdefault('ecache', {})
   477         ecache = self.transaction_data.setdefault('ecache', {})
   483         ecache.setdefault(entity.eid, entity)
   478         ecache.setdefault(entity.eid, entity)
   484 
   479 
   485     @_open_only
   480     @_open_only
   486     def entity_cache(self, eid):
   481     def entity_cache(self, eid):
   776                         operation.handle_event('rollback_event')
   771                         operation.handle_event('rollback_event')
   777                     except BaseException:
   772                     except BaseException:
   778                         self.critical('rollback error', exc_info=sys.exc_info())
   773                         self.critical('rollback error', exc_info=sys.exc_info())
   779                         continue
   774                         continue
   780                 cnxset.rollback()
   775                 cnxset.rollback()
   781                 self.debug('rollback for transaction %s done', self.connectionid)
   776                 self.debug('rollback for transaction %s done', self)
   782         finally:
   777         finally:
   783             self.clear()
   778             self.clear()
   784 
   779 
   785     @_open_only
   780     @_open_only
   786     def commit(self, free_cnxset=None, reset_pool=None):
   781     def commit(self, free_cnxset=None, reset_pool=None):
   822                             processed.append(operation)
   817                             processed.append(operation)
   823                             if debug:
   818                             if debug:
   824                                 print(operation)
   819                                 print(operation)
   825                             operation.handle_event('precommit_event')
   820                             operation.handle_event('precommit_event')
   826                     self.pending_operations[:] = processed
   821                     self.pending_operations[:] = processed
   827                     self.debug('precommit transaction %s done', self.connectionid)
   822                     self.debug('precommit transaction %s done', self)
   828                 except BaseException:
   823                 except BaseException:
   829                     # if error on [pre]commit:
   824                     # if error on [pre]commit:
   830                     #
   825                     #
   831                     # * set .failed = True on the operation causing the failure
   826                     # * set .failed = True on the operation causing the failure
   832                     # * call revert<event>_event on processed operations
   827                     # * call revert<event>_event on processed operations
   866                         try:
   861                         try:
   867                             operation.handle_event('postcommit_event')
   862                             operation.handle_event('postcommit_event')
   868                         except BaseException:
   863                         except BaseException:
   869                             self.critical('error while postcommit',
   864                             self.critical('error while postcommit',
   870                                           exc_info=sys.exc_info())
   865                                           exc_info=sys.exc_info())
   871                 self.debug('postcommit transaction %s done', self.connectionid)
   866                 self.debug('postcommit transaction %s done', self)
   872                 return self.transaction_uuid(set=False)
   867                 return self.transaction_uuid(set=False)
   873         finally:
   868         finally:
   874             self.clear()
   869             self.clear()
   875 
   870 
   876     # resource accessors ######################################################
   871     # resource accessors ######################################################
   928      * user,
   923      * user,
   929      * other session data.
   924      * other session data.
   930     """
   925     """
   931 
   926 
   932     def __init__(self, user, repo, _id=None):
   927     def __init__(self, user, repo, _id=None):
   933         self.sessionid = _id or make_uid(unormalize(user.login))
       
   934         self.user = user  # XXX repoapi: deprecated and store only a login.
   928         self.user = user  # XXX repoapi: deprecated and store only a login.
   935         self.repo = repo
   929         self.repo = repo
   936         self.data = {}
   930         self.data = {}
   937 
   931 
   938     def __unicode__(self):
   932     def __unicode__(self):
   939         return '<session %s (%s 0x%x)>' % (
   933         return '<session %s (0x%x)>' % (
   940             unicode(self.user.login), self.sessionid, id(self))
   934             unicode(self.user.login), id(self))
   941 
       
   942     @property
       
   943     @deprecated('[3.19] session.id is deprecated, use session.sessionid')
       
   944     def id(self):
       
   945         return self.sessionid
       
   946 
   935 
   947     @property
   936     @property
   948     def login(self):
   937     def login(self):
   949         return self.user.login
   938         return self.user.login
   950 
   939