server/session.py
changeset 9122 1d109fb9c67c
parent 9121 182c620c960b
child 9123 c992811edec2
equal deleted inserted replaced
9121:182c620c960b 9122:1d109fb9c67c
    97         return obj.allow_all_hooks_but(*categories)
    97         return obj.allow_all_hooks_but(*categories)
    98     elif mode == HOOKS_DENY_ALL:
    98     elif mode == HOOKS_DENY_ALL:
    99         return obj.deny_all_hooks_but(*categories)
    99         return obj.deny_all_hooks_but(*categories)
   100 
   100 
   101 
   101 
   102 class _hooks_control(object):
   102 class _hooks_control(object): # XXX repoapi: remove me when
       
   103                               # session stop being connection
   103     """context manager to control activated hooks categories.
   104     """context manager to control activated hooks categories.
   104 
   105 
   105     If mode is`HOOKS_DENY_ALL`, given hooks categories will
   106     If mode is`HOOKS_DENY_ALL`, given hooks categories will
   106     be enabled.
   107     be enabled.
   107 
   108 
   147                 else:
   148                 else:
   148                     self.cnx.enable_hook_categories(*self.categories)
   149                     self.cnx.enable_hook_categories(*self.categories)
   149         finally:
   150         finally:
   150             self.cnx.hooks_mode = self.oldmode
   151             self.cnx.hooks_mode = self.oldmode
   151 
   152 
   152 class _session_hooks_control(_hooks_control):
   153 class _session_hooks_control(_hooks_control): # XXX repoapi: remove me when
       
   154                                               # session stop being connection
   153     """hook control context manager for session
   155     """hook control context manager for session
   154 
   156 
   155     Necessary to handle some unholy transaction scope logic."""
   157     Necessary to handle some unholy transaction scope logic."""
   156 
   158 
   157 
   159 
  1182 def cnx_attr(attr_name, writable=False):
  1184 def cnx_attr(attr_name, writable=False):
  1183     """return a property to forward attribute access to connection.
  1185     """return a property to forward attribute access to connection.
  1184 
  1186 
  1185     This is to be used by session"""
  1187     This is to be used by session"""
  1186     args = {}
  1188     args = {}
       
  1189     @deprecated('[4.0] use a Connection object instead')
  1187     def attr_from_cnx(session):
  1190     def attr_from_cnx(session):
  1188         return getattr(session._cnx, attr_name)
  1191         return getattr(session._cnx, attr_name)
  1189     args['fget'] = attr_from_cnx
  1192     args['fget'] = attr_from_cnx
  1190     if writable:
  1193     if writable:
       
  1194         @deprecated('[4.0] use a Connection object instead')
  1191         def write_attr(session, value):
  1195         def write_attr(session, value):
  1192             return setattr(session._cnx, attr_name, value)
  1196             return setattr(session._cnx, attr_name, value)
  1193         args['fset'] = write_attr
  1197         args['fset'] = write_attr
  1194     return property(**args)
  1198     return property(**args)
  1195 
  1199 
  1196 def cnx_meth(meth_name):
  1200 def cnx_meth(meth_name):
  1197     """return a function forwarding calls to connection.
  1201     """return a function forwarding calls to connection.
  1198 
  1202 
  1199     This is to be used by session"""
  1203     This is to be used by session"""
       
  1204     @deprecated('[4.0] use a Connection object instead')
  1200     def meth_from_cnx(session, *args, **kwargs):
  1205     def meth_from_cnx(session, *args, **kwargs):
  1201         result = getattr(session._cnx, meth_name)(*args, **kwargs)
  1206         result = getattr(session._cnx, meth_name)(*args, **kwargs)
  1202         if getattr(result, '_cw', None) is not None:
  1207         if getattr(result, '_cw', None) is not None:
  1203             result._cw = session
  1208             result._cw = session
  1204         return result
  1209         return result
  1214 
  1219 
  1215     def __float__(self):
  1220     def __float__(self):
  1216         return float(self.value)
  1221         return float(self.value)
  1217 
  1222 
  1218 
  1223 
  1219 class Session(RequestSessionBase):
  1224 class Session(RequestSessionBase): # XXX repoapi: stop being a
       
  1225                                    # RequestSessionBase at some point
  1220     """Repository user session
  1226     """Repository user session
  1221 
  1227 
  1222     This tie all together:
  1228     This tie all together:
  1223      * session id,
  1229      * session id,
  1224      * user,
  1230      * user,
  1331     is_request = False
  1337     is_request = False
  1332     is_internal_session = False
  1338     is_internal_session = False
  1333 
  1339 
  1334     def __init__(self, user, repo, cnxprops=None, _id=None):
  1340     def __init__(self, user, repo, cnxprops=None, _id=None):
  1335         super(Session, self).__init__(repo.vreg)
  1341         super(Session, self).__init__(repo.vreg)
  1336         self.id = _id or make_uid(unormalize(user.login).encode('UTF8'))
  1342         self.sessionid = _id or make_uid(unormalize(user.login).encode('UTF8'))
  1337         self.user = user
  1343         self.user = user # XXX repoapi: deprecated and store only a login.
  1338         self.repo = repo
  1344         self.repo = repo
  1339         self._timestamp = Timestamp()
  1345         self._timestamp = Timestamp()
  1340         self.default_mode = 'read'
  1346         self.default_mode = 'read'
  1341         # short cut to querier .execute method
  1347         # short cut to querier .execute method
  1342         self._execute = repo.querier.execute
  1348         self._execute = repo.querier.execute
  1345         self.data = {}
  1351         self.data = {}
  1346         # i18n initialization
  1352         # i18n initialization
  1347         self.set_language(user.prefered_language())
  1353         self.set_language(user.prefered_language())
  1348         ### internals
  1354         ### internals
  1349         # Connection of this section
  1355         # Connection of this section
  1350         self._cnxs = {}
  1356         self._cnxs = {} # XXX repoapi: remove this when nobody use the session
       
  1357                         # as a Connection
  1351         # Data local to the thread
  1358         # Data local to the thread
  1352         self.__threaddata = threading.local()
  1359         self.__threaddata = threading.local() # XXX repoapi: remove this when
       
  1360                                               # nobody use the session as a Connection
  1353         self._cnxset_tracker = CnxSetTracker()
  1361         self._cnxset_tracker = CnxSetTracker()
  1354         self._closed = False
  1362         self._closed = False
  1355         self._lock = threading.RLock()
  1363         self._lock = threading.RLock()
  1356 
  1364 
  1357     def __unicode__(self):
  1365     def __unicode__(self):
  1360     @property
  1368     @property
  1361     def timestamp(self):
  1369     def timestamp(self):
  1362         return float(self._timestamp)
  1370         return float(self._timestamp)
  1363 
  1371 
  1364     @property
  1372     @property
  1365     def sessionid(self):
  1373     @deprecated('[4.0] session.id is deprecated. use session.sessionid')
  1366         return self.id
  1374     def id(self):
       
  1375         return self.sessionid
  1367 
  1376 
  1368     @property
  1377     @property
  1369     def login(self):
  1378     def login(self):
  1370         # XXX backward compat with dbapi. deprecate me ASAP.
       
  1371         return self.user.login
  1379         return self.user.login
  1372 
  1380 
  1373     def new_cnx(self):
  1381     def new_cnx(self):
  1374         """Return a new Connection object linked to the session
  1382         """Return a new Connection object linked to the session
  1375 
  1383 
  1404                 del self.__threaddata.cnx
  1412                 del self.__threaddata.cnx
  1405         except AttributeError:
  1413         except AttributeError:
  1406             pass
  1414             pass
  1407 
  1415 
  1408     def set_cnx(self, cnxid=None):
  1416     def set_cnx(self, cnxid=None):
       
  1417         # XXX repoapi: remove this when nobody use the session as a Connection
  1409         """set the default connection of the current thread to <cnxid>
  1418         """set the default connection of the current thread to <cnxid>
  1410 
  1419 
  1411         Connection is created if necessary"""
  1420         Connection is created if necessary"""
  1412         if cnxid is None:
  1421         if cnxid is None:
  1413             cnxid = threading.currentThread().getName()
  1422             cnxid = threading.currentThread().getName()
  1423             return self.__threaddata.cnx
  1432             return self.__threaddata.cnx
  1424         except AttributeError:
  1433         except AttributeError:
  1425             self.set_cnx()
  1434             self.set_cnx()
  1426             return self.__threaddata.cnx
  1435             return self.__threaddata.cnx
  1427 
  1436 
       
  1437     @deprecated('[4.0] use a Connection object instead')
  1428     def get_option_value(self, option, foreid=None):
  1438     def get_option_value(self, option, foreid=None):
  1429         return self.repo.get_option_value(option, foreid)
  1439         return self.repo.get_option_value(option, foreid)
  1430 
  1440 
       
  1441     @deprecated('[4.0] use a Connection object instead')
  1431     def transaction(self, free_cnxset=True):
  1442     def transaction(self, free_cnxset=True):
  1432         """return context manager to enter a transaction for the session: when
  1443         """return context manager to enter a transaction for the session: when
  1433         exiting the `with` block on exception, call `session.rollback()`, else
  1444         exiting the `with` block on exception, call `session.rollback()`, else
  1434         call `session.commit()` on normal exit.
  1445         call `session.commit()` on normal exit.
  1435 
  1446 
  1454     added_in_transaction = cnx_meth('added_in_transaction')
  1465     added_in_transaction = cnx_meth('added_in_transaction')
  1455     rtype_eids_rdef = cnx_meth('rtype_eids_rdef')
  1466     rtype_eids_rdef = cnx_meth('rtype_eids_rdef')
  1456 
  1467 
  1457     # security control #########################################################
  1468     # security control #########################################################
  1458 
  1469 
  1459 
  1470     @deprecated('[4.0] use a Connection object instead')
  1460     def security_enabled(self, read=None, write=None):
  1471     def security_enabled(self, read=None, write=None):
  1461         return _session_security_enabled(self, read=read, write=write)
  1472         return _session_security_enabled(self, read=read, write=write)
  1462 
  1473 
  1463     read_security = cnx_attr('read_security', writable=True)
  1474     read_security = cnx_attr('read_security', writable=True)
  1464     write_security = cnx_attr('write_security', writable=True)
  1475     write_security = cnx_attr('write_security', writable=True)
  1465     running_dbapi_query = cnx_attr('running_dbapi_query')
  1476     running_dbapi_query = cnx_attr('running_dbapi_query')
  1466 
  1477 
  1467     # hooks activation control #################################################
  1478     # hooks activation control #################################################
  1468     # all hooks should be activated during normal execution
  1479     # all hooks should be activated during normal execution
  1469 
  1480 
       
  1481 
       
  1482     @deprecated('[4.0] use a Connection object instead')
  1470     def allow_all_hooks_but(self, *categories):
  1483     def allow_all_hooks_but(self, *categories):
  1471         return _session_hooks_control(self, HOOKS_ALLOW_ALL, *categories)
  1484         return _session_hooks_control(self, HOOKS_ALLOW_ALL, *categories)
       
  1485     @deprecated('[4.0] use a Connection object instead')
  1472     def deny_all_hooks_but(self, *categories):
  1486     def deny_all_hooks_but(self, *categories):
  1473         return _session_hooks_control(self, HOOKS_DENY_ALL, *categories)
  1487         return _session_hooks_control(self, HOOKS_DENY_ALL, *categories)
  1474 
  1488 
  1475     hooks_mode = cnx_attr('hooks_mode')
  1489     hooks_mode = cnx_attr('hooks_mode')
  1476 
  1490 
  1481     is_hook_category_activated = cnx_meth('is_hook_category_activated')
  1495     is_hook_category_activated = cnx_meth('is_hook_category_activated')
  1482     is_hook_activated = cnx_meth('is_hook_activated')
  1496     is_hook_activated = cnx_meth('is_hook_activated')
  1483 
  1497 
  1484     # connection management ###################################################
  1498     # connection management ###################################################
  1485 
  1499 
       
  1500     @deprecated('[4.0] use a Connection object instead')
  1486     def keep_cnxset_mode(self, mode):
  1501     def keep_cnxset_mode(self, mode):
  1487         """set `mode`, e.g. how the session will keep its connections set:
  1502         """set `mode`, e.g. how the session will keep its connections set:
  1488 
  1503 
  1489         * if mode == 'write', the connections set is freed after each ready
  1504         * if mode == 'write', the connections set is freed after each ready
  1490           query, but kept until the transaction's end (eg commit or rollback)
  1505           query, but kept until the transaction's end (eg commit or rollback)
  1505 
  1520 
  1506     mode = cnx_attr('mode', writable=True)
  1521     mode = cnx_attr('mode', writable=True)
  1507     commit_state = cnx_attr('commit_state', writable=True)
  1522     commit_state = cnx_attr('commit_state', writable=True)
  1508 
  1523 
  1509     @property
  1524     @property
       
  1525     @deprecated('[4.0] use a Connection object instead')
  1510     def cnxset(self):
  1526     def cnxset(self):
  1511         """connections set, set according to transaction mode for each query"""
  1527         """connections set, set according to transaction mode for each query"""
  1512         if self._closed:
  1528         if self._closed:
  1513             self.free_cnxset(True)
  1529             self.free_cnxset(True)
  1514             raise SessionClosedError('try to access connections set on a closed session %s' % self.id)
  1530             raise SessionClosedError('try to access connections set on a closed session %s' % self.id)
  1560     call_service = cnx_meth('call_service')
  1576     call_service = cnx_meth('call_service')
  1561 
  1577 
  1562     # request interface #######################################################
  1578     # request interface #######################################################
  1563 
  1579 
  1564     @property
  1580     @property
       
  1581     @deprecated('[4.0] use a Connection object instead')
  1565     def cursor(self):
  1582     def cursor(self):
  1566         """return a rql cursor"""
  1583         """return a rql cursor"""
  1567         return self
  1584         return self
  1568 
  1585 
  1569     set_entity_cache  = cnx_meth('set_entity_cache')
  1586     set_entity_cache  = cnx_meth('set_entity_cache')
  1574     source_defs = cnx_meth('source_defs')
  1591     source_defs = cnx_meth('source_defs')
  1575     describe = cnx_meth('describe')
  1592     describe = cnx_meth('describe')
  1576     source_from_eid = cnx_meth('source_from_eid')
  1593     source_from_eid = cnx_meth('source_from_eid')
  1577 
  1594 
  1578 
  1595 
       
  1596     @deprecated('[4.0] use a Connection object instead')
  1579     def execute(self, *args, **kwargs):
  1597     def execute(self, *args, **kwargs):
  1580         """db-api like method directly linked to the querier execute method.
  1598         """db-api like method directly linked to the querier execute method.
  1581 
  1599 
  1582         See :meth:`cubicweb.dbapi.Cursor.execute` documentation.
  1600         See :meth:`cubicweb.dbapi.Cursor.execute` documentation.
  1583         """
  1601         """
  1602                 else:
  1620                 else:
  1603                     cnx.clear()
  1621                     cnx.clear()
  1604             else:
  1622             else:
  1605                 cnx.clear()
  1623                 cnx.clear()
  1606 
  1624 
       
  1625     @deprecated('[4.0] use a Connection object instead')
  1607     def commit(self, free_cnxset=True, reset_pool=None):
  1626     def commit(self, free_cnxset=True, reset_pool=None):
  1608         """commit the current session's transaction"""
  1627         """commit the current session's transaction"""
  1609         cstate = self._cnx.commit_state
  1628         cstate = self._cnx.commit_state
  1610         if cstate == 'uncommitable':
  1629         if cstate == 'uncommitable':
  1611             raise QueryError('transaction must be rollbacked')
  1630             raise QueryError('transaction must be rollbacked')
  1612         try:
  1631         try:
  1613             return self._cnx.commit(free_cnxset, reset_pool)
  1632             return self._cnx.commit(free_cnxset, reset_pool)
  1614         finally:
  1633         finally:
  1615             self._clear_thread_data(free_cnxset)
  1634             self._clear_thread_data(free_cnxset)
  1616 
  1635 
       
  1636     @deprecated('[4.0] use a Connection object instead')
  1617     def rollback(self, free_cnxset=True, **kwargs):
  1637     def rollback(self, free_cnxset=True, **kwargs):
  1618         """rollback the current session's transaction"""
  1638         """rollback the current session's transaction"""
  1619         try:
  1639         try:
  1620             return self._cnx.rollback(free_cnxset, **kwargs)
  1640             return self._cnx.rollback(free_cnxset, **kwargs)
  1621         finally:
  1641         finally:
  1676     rql_rewriter = cnx_attr('_rewriter')
  1696     rql_rewriter = cnx_attr('_rewriter')
  1677 
  1697 
  1678     # deprecated ###############################################################
  1698     # deprecated ###############################################################
  1679 
  1699 
  1680     @property
  1700     @property
       
  1701     @deprecated('[4.0] use a Connection object instead')
  1681     def anonymous_session(self):
  1702     def anonymous_session(self):
  1682         # XXX for now, anonymous-user is a web side option.
  1703         # XXX for now, anonymous-user is a web side option.
  1683         # It will only be present inside all-in-one instance.
  1704         # It will only be present inside all-in-one instance.
  1684         # there is plan to move it down to global config.
  1705         # there is plan to move it down to global config.
  1685         return self.user.login == self.repo.config.get('anonymous-user')
  1706         return self.user.login == self.repo.config.get('anonymous-user')