server/session.py
branchtls-sprint
changeset 1660 d1030dd9730b
parent 1263 01152fffd593
child 1880 293fe4b49e28
--- a/server/session.py	Mon May 04 16:22:47 2009 +0200
+++ b/server/session.py	Mon May 04 17:03:30 2009 +0200
@@ -13,7 +13,7 @@
 from rql.nodes import VariableRef, Function, ETYPE_PYOBJ_MAP, etype_from_pyobj
 from yams import BASE_TYPES
 
-from cubicweb import RequestSessionMixIn, Binary
+from cubicweb import RequestSessionMixIn, Binary, UnknownEid
 from cubicweb.dbapi import ConnectionProperties
 from cubicweb.utils import make_uid
 from cubicweb.server.rqlrewrite import RQLRewriter
@@ -29,7 +29,7 @@
                 continue
             if etype in BASE_TYPES:
                 return True
-            return False   
+            return False
 
 def _make_description(selected, args, solution):
     """return a description for a result set"""
@@ -45,7 +45,7 @@
     """tie session id, user, connections pool and other session data all
     together
     """
-    
+
     def __init__(self, user, repo, cnxprops=None, _id=None):
         super(Session, self).__init__(repo.vreg)
         self.id = _id or make_uid(user.login.encode('UTF8'))
@@ -65,7 +65,7 @@
         # i18n initialization
         self.set_language(cnxprops.lang)
         self._threaddata = threading.local()
-        
+
     def get_mode(self):
         return getattr(self._threaddata, 'mode', 'read')
     def set_mode(self, value):
@@ -78,12 +78,12 @@
     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)
-    
+
     # pending transaction operations
     @property
     def pending_operations(self):
@@ -92,7 +92,7 @@
         except AttributeError:
             self._threaddata.pending_operations = []
             return self._threaddata.pending_operations
-    
+
     # rql rewriter
     @property
     def rql_rewriter(self):
@@ -101,7 +101,7 @@
         except AttributeError:
             self._threaddata._rewriter = RQLRewriter(self.repo.querier, self)
             return self._threaddata._rewriter
-    
+
     # transaction queries data
     @property
     def _query_data(self):
@@ -110,7 +110,7 @@
         except AttributeError:
             self._threaddata._query_data = {}
             return self._threaddata._query_data
-    
+
     def set_language(self, language):
         """i18n configuration for translation"""
         vreg = self.vreg
@@ -124,42 +124,42 @@
             except KeyError:
                 self._ = self.__ = unicode
         self.lang = language
-        
+
     def change_property(self, prop, value):
         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, 
+        return '<%ssession %s (%s 0x%x)>' % (self.cnxtype, self.user.login,
                                              self.id, id(self))
 
     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)
-        
+
     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'
-        
+
     def set_pool(self):
         """the session need a pool to execute some queries"""
         if self.pool is None:
             self._threaddata.pool = self.repo._get_pool()
-            try:                
+            try:
                 self._threaddata.pool.pool_set(self)
             except:
                 self.repo._free_pool(self.pool)
                 self._threaddata.pool = None
                 raise
         return self._threaddata.pool
-            
+
     def reset_pool(self):
         """the session has no longer using its pool, at least for some time
         """
@@ -170,7 +170,7 @@
             self.repo._free_pool(self.pool)
             self.pool.pool_reset(self)
             self._threaddata.pool = None
-            
+
     def system_sql(self, sql, args=None):
         """return a sql cursor on the system database"""
         if not sql.split(None, 1)[0].upper() == 'SELECT':
@@ -181,26 +181,26 @@
 
     def actual_session(self):
         """return the original parent session if any, else self"""
-        return self        
+        return self
 
     # shared data handling ###################################################
-    
+
     def get_shared_data(self, key, default=None, pop=False):
         """return value associated to `key` in session data"""
         if pop:
             return self.data.pop(key, default)
         else:
             return self.data.get(key, default)
-        
+
     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)
         else:
             self.data[key] = value
-        
+
     # request interface #######################################################
-    
+
     def set_entity_cache(self, entity):
         # no entity cache in the server, too high risk of inconsistency
         # between pre/post hooks
@@ -211,20 +211,20 @@
 
     def base_url(self):
         return self.repo.config['base-url'] or u''
-        
+
     def from_controller(self):
         """return the id (string) of the controller issuing the request (no
         sense here, always return 'view')
         """
         return 'view'
-    
+
     def source_defs(self):
         return self.repo.source_defs()
 
     def describe(self, eid):
         """return a tuple (type, sourceuri, extid) for the entity with id <eid>"""
         return self.repo.type_and_source_from_eid(eid, self)
-    
+
     # db-api like interface ###################################################
 
     def source_from_eid(self, eid):
@@ -249,7 +249,7 @@
         # need shared pool set
         self.set_pool()
         return csession
-        
+
     def unsafe_execute(self, rql, kwargs=None, eid_key=None, build_descr=False,
                        propagate=False):
         """like .execute but with security checking disabled (this method is
@@ -266,7 +266,7 @@
     def cursor(self):
         """return a rql cursor"""
         return self
-    
+
     def execute(self, rql, kwargs=None, eid_key=None, build_descr=True,
                 propagate=False):
         """db-api like method directly linked to the querier execute method
@@ -276,7 +276,7 @@
         """
         rset = self._execute(self, rql, kwargs, eid_key, build_descr)
         return self.decorate_rset(rset, propagate)
-    
+
     def commit(self, reset_pool=True):
         """commit the current session's transaction"""
         if self.pool is None:
@@ -317,7 +317,7 @@
             self._query_data.clear()
             if reset_pool:
                 self.reset_pool()
-                        
+
     def rollback(self, reset_pool=True):
         """rollback the current session's transaction"""
         if self.pool is None:
@@ -340,19 +340,19 @@
             self._query_data.clear()
             if reset_pool:
                 self.reset_pool()
-        
+
     def close(self):
         """do not close pool on session close, since they are shared now"""
         self.rollback()
-        
+
     # transaction data/operations management ##################################
-    
+
     def add_query_data(self, key, value):
         self._query_data.setdefault(key, []).append(value)
-    
+
     def set_query_data(self, key, value):
         self._query_data[key] = value
-        
+
     def query_data(self, key, default=None, setdefault=False, pop=False):
         if setdefault:
             assert not pop
@@ -361,7 +361,7 @@
             return self._query_data.pop(key, default)
         else:
             return self._query_data.get(key, default)
-        
+
     def add_operation(self, operation, index=None):
         """add an observer"""
         assert self.commit_state != 'commit'
@@ -369,9 +369,9 @@
             self.pending_operations.insert(index, operation)
         else:
             self.pending_operations.append(operation)
-            
+
     # querier helpers #########################################################
-    
+
     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:
@@ -385,7 +385,7 @@
 
     def manual_build_descr(self, rqlst, args, result):
         """build a description for a given result by analysing each row
-        
+
         XXX could probably be done more efficiently during execution of query
         """
         # not so easy, looks for variable which changes from one solution
@@ -410,7 +410,7 @@
         if not todetermine:
             return [tuple(basedescription)] * len(result)
         return self._build_descr(result, basedescription, todetermine)
-    
+
     def _build_descr(self, result, basedescription, todetermine):
         description = []
         etype_from_eid = self.describe
@@ -422,23 +422,23 @@
                     # None value inserted by an outer join, no type
                     row_descr[index] = None
                     continue
-                try:
-                    if isfinal:
-                        row_descr[index] = etype_from_pyobj(value)
-                    else:
+                if isfinal:
+                    row_descr[index] = etype_from_pyobj(value)
+                else:
+                    try:
                         row_descr[index] = etype_from_eid(value)[0]
-                except UnknownEid:
-                    self.critical('wrong eid in repository, should check database')
-                    row_descr[index] = row[index] = None
+                    except UnknownEid:
+                        self.critical('wrong eid %s in repository, should check database' % value)
+                        row_descr[index] = row[index] = None
             description.append(tuple(row_descr))
         return description
 
-    
+
 class ChildSession(Session):
     """child (or internal) session are used to hijack the security system
     """
     cnxtype = 'inmemory'
-    
+
     def __init__(self, parent_session):
         self.id = None
         self.is_internal_session = False
@@ -454,7 +454,7 @@
         self._ = self.__ = parent_session._
         # short cut to querier .execute method
         self._execute = self.repo.querier.execute
-    
+
     @property
     def super_session(self):
         return self
@@ -470,7 +470,7 @@
     def set_commit_state(self, value):
         self.parent_session.set_commit_state(value)
     commit_state = property(get_commit_state, set_commit_state)
-    
+
     @property
     def pool(self):
         return self.parent_session.pool
@@ -480,11 +480,11 @@
     @property
     def _query_data(self):
         return self.parent_session._query_data
-        
+
     def set_pool(self):
         """the session need a pool to execute some queries"""
         self.parent_session.set_pool()
-            
+
     def reset_pool(self):
         """the session has no longer using its pool, at least for some time
         """
@@ -493,19 +493,19 @@
     def actual_session(self):
         """return the original parent session if any, else self"""
         return self.parent_session
-        
+
     def commit(self, reset_pool=True):
         """commit the current session's transaction"""
         self.parent_session.commit(reset_pool)
-        
+
     def rollback(self, reset_pool=True):
         """rollback the current session's transaction"""
         self.parent_session.rollback(reset_pool)
-        
+
     def close(self):
         """do not close pool on session close, since they are shared now"""
         self.rollback()
-        
+
     def user_data(self):
         """returns a dictionnary with this user's information"""
         return self.parent_session.user_data()
@@ -513,14 +513,14 @@
 
 class InternalSession(Session):
     """special session created internaly by the repository"""
-    
+
     def __init__(self, repo, cnxprops=None):
         super(InternalSession, self).__init__(_IMANAGER, repo, cnxprops,
                                               _id='internal')
         self.cnxtype = 'inmemory'
         self.is_internal_session = True
         self.is_super_session = True
-    
+
     @property
     def super_session(self):
         return self
@@ -544,7 +544,7 @@
 
     def owns(self, eid):
         return True
-    
+
     def has_permission(self, pname, contexteid=None):
         return True