simplify transaction data api, reorganize code stable
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Thu, 11 Jun 2009 19:04:20 +0200
branchstable
changeset 2100 89b825cdec74
parent 2099 0cba78f4fa12
child 2101 08003e0354a7
simplify transaction data api, reorganize code
server/session.py
--- a/server/session.py	Wed Jun 10 23:29:37 2009 +0200
+++ b/server/session.py	Thu Jun 11 19:04:20 2009 +0200
@@ -11,6 +11,7 @@
 import threading
 from time import time
 
+from logilab.common.deprecation import obsolete
 from rql.nodes import VariableRef, Function, ETYPE_PYOBJ_MAP, etype_from_pyobj
 from yams import BASE_TYPES
 
@@ -65,54 +66,35 @@
         self.data = {}
         # i18n initialization
         self.set_language(cnxprops.lang)
+        # internals
         self._threaddata = threading.local()
         self._threads_in_transaction = set()
         self._closed = False
 
-    def get_mode(self):
-        return getattr(self._threaddata, 'mode', 'read')
-    def set_mode(self, value):
-        self._threaddata.mode = value
-    # transaction mode (read/write), resetted to read on commit / rollback
-    mode = property(get_mode, set_mode)
+    def __str__(self):
+        return '<%ssession %s (%s 0x%x)>' % (self.cnxtype, self.user.login,
+                                             self.id, id(self))
+    # resource accessors ######################################################
 
-    def get_commit_state(self):
-        return getattr(self._threaddata, 'commit_state', None)
-    def set_commit_state(self, value):
-        self._threaddata.commit_state = value
-    commit_state = property(get_commit_state, set_commit_state)
-
-    # set according to transaction mode for each query
-    @property
-    def pool(self):
-        return getattr(self._threaddata, 'pool', None)
+    def actual_session(self):
+        """return the original parent session if any, else self"""
+        return self
 
-    # pending transaction operations
-    @property
-    def pending_operations(self):
-        try:
-            return self._threaddata.pending_operations
-        except AttributeError:
-            self._threaddata.pending_operations = []
-            return self._threaddata.pending_operations
+    def etype_class(self, etype):
+        """return an entity class for the given entity type"""
+        return self.vreg.etype_class(etype)
+
+    def entity(self, eid):
+        """return a result set for the given eid"""
+        return self.eid_rset(eid).get_entity(0, 0)
 
-    # rql rewriter
-    @property
-    def rql_rewriter(self):
-        try:
-            return self._threaddata._rewriter
-        except AttributeError:
-            self._threaddata._rewriter = RQLRewriter(self.repo.querier, self)
-            return self._threaddata._rewriter
-
-    # transaction queries data
-    @property
-    def _query_data(self):
-        try:
-            return self._threaddata._query_data
-        except AttributeError:
-            self._threaddata._query_data = {}
-            return self._threaddata._query_data
+    def system_sql(self, sql, args=None):
+        """return a sql cursor on the system database"""
+        if not sql.split(None, 1)[0].upper() == 'SELECT':
+            self.mode = 'write'
+        cursor = self.pool['system']
+        self.pool.source('system').doexec(cursor, sql, args)
+        return cursor
 
     def set_language(self, language):
         """i18n configuration for translation"""
@@ -132,24 +114,26 @@
         assert prop == 'lang' # this is the only one changeable property for now
         self.set_language(value)
 
-    def __str__(self):
-        return '<%ssession %s (%s 0x%x)>' % (self.cnxtype, self.user.login,
-                                             self.id, id(self))
+    # connection management ###################################################
 
-    def etype_class(self, etype):
-        """return an entity class for the given entity type"""
-        return self.vreg.etype_class(etype)
+    def get_mode(self):
+        return getattr(self._threaddata, 'mode', 'read')
+    def set_mode(self, value):
+        self._threaddata.mode = value
+    mode = property(get_mode, set_mode,
+                    doc='transaction mode (read/write), resetted to read on '
+                    'commit / rollback')
 
-    def entity(self, eid):
-        """return a result set for the given eid"""
-        return self.eid_rset(eid).get_entity(0, 0)
+    def get_commit_state(self):
+        return getattr(self._threaddata, 'commit_state', None)
+    def set_commit_state(self, value):
+        self._threaddata.commit_state = value
+    commit_state = property(get_commit_state, set_commit_state)
 
-    def _touch(self):
-        """update latest session usage timestamp and reset mode to read
-        """
-        self.timestamp = time()
-        self.local_perm_cache.clear()
-        self._threaddata.mode = 'read'
+    @property
+    def pool(self):
+        """connections pool, set according to transaction mode for each query"""
+        return getattr(self._threaddata, 'pool', None)
 
     def set_pool(self):
         """the session need a pool to execute some queries"""
@@ -168,8 +152,7 @@
         return self._threaddata.pool
 
     def reset_pool(self):
-        """the session has no longer using its pool, at least for some time
-        """
+        """the session has no longer using its pool, at least for some time"""
         # pool may be none if no operation has been done since last commit
         # or rollback
         if self.pool is not None and self.mode == 'read':
@@ -181,17 +164,11 @@
             # free pool once everything is done to avoid race-condition
             self.repo._free_pool(pool)
 
-    def system_sql(self, sql, args=None):
-        """return a sql cursor on the system database"""
-        if not sql.split(None, 1)[0].upper() == 'SELECT':
-            self.mode = 'write'
-        cursor = self.pool['system']
-        self.pool.source('system').doexec(cursor, sql, args)
-        return cursor
-
-    def actual_session(self):
-        """return the original parent session if any, else self"""
-        return self
+    def _touch(self):
+        """update latest session usage timestamp and reset mode to read"""
+        self.timestamp = time()
+        self.local_perm_cache.clear()
+        self._threaddata.mode = 'read'
 
     # shared data handling ###################################################
 
@@ -205,7 +182,7 @@
     def set_shared_data(self, key, value, querydata=False):
         """set value associated to `key` in session data"""
         if querydata:
-            self.set_query_data(key, value)
+            self.transaction_data[key] = value
         else:
             self.data[key] = value
 
@@ -291,7 +268,7 @@
         """commit the current session's transaction"""
         if self.pool is None:
             assert not self.pending_operations
-            self._query_data.clear()
+            self.transaction_data.clear()
             self._touch()
             return
         if self.commit_state:
@@ -324,7 +301,7 @@
             self._touch()
             self.commit_state = None
             self.pending_operations[:] = []
-            self._query_data.clear()
+            self.transaction_data.clear()
             if reset_pool:
                 self.reset_pool()
 
@@ -332,7 +309,7 @@
         """rollback the current session's transaction"""
         if self.pool is None:
             assert not self.pending_operations
-            self._query_data.clear()
+            self.transaction_data.clear()
             self._touch()
             return
         try:
@@ -347,7 +324,7 @@
         finally:
             self._touch()
             self.pending_operations[:] = []
-            self._query_data.clear()
+            self.transaction_data.clear()
             if reset_pool:
                 self.reset_pool()
 
@@ -374,20 +351,32 @@
 
     # transaction data/operations management ##################################
 
-    def add_query_data(self, key, value):
-        self._query_data.setdefault(key, []).append(value)
+    @property
+    def transaction_data(self):
+        try:
+            return self._threaddata.transaction_data
+        except AttributeError:
+            self._threaddata.transaction_data = {}
+            return self._threaddata.transaction_data
 
-    def set_query_data(self, key, value):
-        self._query_data[key] = value
-
+    @obsolete('use direct access to session.transaction_data')
     def query_data(self, key, default=None, setdefault=False, pop=False):
         if setdefault:
             assert not pop
-            return self._query_data.setdefault(key, default)
+            return self.transaction_data.setdefault(key, default)
         if pop:
-            return self._query_data.pop(key, default)
+            return self.transaction_data.pop(key, default)
         else:
-            return self._query_data.get(key, default)
+            return self.transaction_data.get(key, default)
+
+    @property
+    def pending_operations(self):
+        try:
+            return self._threaddata.pending_operations
+        except AttributeError:
+            self._threaddata.pending_operations = []
+            return self._threaddata.pending_operations
+
 
     def add_operation(self, operation, index=None):
         """add an observer"""
@@ -399,6 +388,14 @@
 
     # querier helpers #########################################################
 
+    @property
+    def rql_rewriter(self):
+        try:
+            return self._threaddata._rewriter
+        except AttributeError:
+            self._threaddata._rewriter = RQLRewriter(self.repo.querier, self)
+            return self._threaddata._rewriter
+
     def build_description(self, rqlst, args, result):
         """build a description for a given result"""
         if len(rqlst.children) == 1 and len(rqlst.children[0].solutions) == 1:
@@ -505,8 +502,8 @@
     def pending_operations(self):
         return self.parent_session.pending_operations
     @property
-    def _query_data(self):
-        return self.parent_session._query_data
+    def transaction_data(self):
+        return self.parent_session.transaction_data
 
     def set_pool(self):
         """the session need a pool to execute some queries"""