server/session.py
changeset 10346 b926ff4ef4a8
parent 10345 ef54ea75a642
child 10347 52a976c5d27a
equal deleted inserted replaced
10345:ef54ea75a642 10346:b926ff4ef4a8
   437       read/write security is currently activated.
   437       read/write security is currently activated.
   438 
   438 
   439     """
   439     """
   440 
   440 
   441     is_request = False
   441     is_request = False
       
   442     mode = 'read'
   442 
   443 
   443     def __init__(self, session, cnxid=None, session_handled=False):
   444     def __init__(self, session, cnxid=None, session_handled=False):
   444         # using super(Connection, self) confuse some test hack
   445         # using super(Connection, self) confuse some test hack
   445         RequestSessionBase.__init__(self, session.vreg)
   446         RequestSessionBase.__init__(self, session.vreg)
   446         # only the session provide explicite
   447         # only the session provide explicite
   471         self._execute = self.repo.querier.execute
   472         self._execute = self.repo.querier.execute
   472 
   473 
   473         # other session utility
   474         # other session utility
   474         self._session_timestamp = session._timestamp
   475         self._session_timestamp = session._timestamp
   475 
   476 
   476         #: connection handling mode
       
   477         self.mode = session.default_mode
       
   478         #: connection set used to execute queries on sources
   477         #: connection set used to execute queries on sources
   479         self._cnxset = None
   478         self._cnxset = None
   480         #: CnxSetTracker used to report cnxset usage
   479         #: CnxSetTracker used to report cnxset usage
   481         self._cnxset_tracker = session._cnxset_tracker
   480         self._cnxset_tracker = CnxSetTracker()
   482         #: is this connection from a client or internal to the repo
   481         #: is this connection from a client or internal to the repo
   483         self.running_dbapi_query = True
   482         self.running_dbapi_query = True
   484         # internal (root) session
   483         # internal (root) session
   485         self.is_internal_session = isinstance(session.user, InternalManager)
   484         self.is_internal_session = isinstance(session.user, InternalManager)
   486 
   485 
  1224 
  1223 
  1225     def __float__(self):
  1224     def __float__(self):
  1226         return float(self.value)
  1225         return float(self.value)
  1227 
  1226 
  1228 
  1227 
  1229 class Session(RequestSessionBase): # XXX repoapi: stop being a
  1228 class Session(object):
  1230                                    # RequestSessionBase at some point
       
  1231     """Repository user session
  1229     """Repository user session
  1232 
  1230 
  1233     This ties all together:
  1231     This ties all together:
  1234      * session id,
  1232      * session id,
  1235      * user,
  1233      * user,
  1236      * connections set,
       
  1237      * other session data.
  1234      * other session data.
  1238 
       
  1239     **About session storage / transactions**
       
  1240 
       
  1241     Here is a description of internal session attributes. Besides :attr:`data`
       
  1242     and :attr:`transaction_data`, you should not have to use attributes
       
  1243     described here but higher level APIs.
       
  1244 
       
  1245       :attr:`data` is a dictionary containing shared data, used to communicate
       
  1246       extra information between the client and the repository
       
  1247 
       
  1248       :attr:`_cnxs` is a dictionary of :class:`Connection` instance, one
       
  1249       for each running connection. The key is the connection id. By default
       
  1250       the connection id is the thread name but it can be otherwise (per dbapi
       
  1251       cursor for instance, or per thread name *from another process*).
       
  1252 
       
  1253       :attr:`__threaddata` is a thread local storage whose `cnx` attribute
       
  1254       refers to the proper instance of :class:`Connection` according to the
       
  1255       connection.
       
  1256 
       
  1257     You should not have to use neither :attr:`_cnx` nor :attr:`__threaddata`,
       
  1258     simply access connection data transparently through the :attr:`_cnx`
       
  1259     property. Also, you usually don't have to access it directly since current
       
  1260     connection's data may be accessed/modified through properties / methods:
       
  1261 
       
  1262       :attr:`connection_data`, similarly to :attr:`data`, is a dictionary
       
  1263       containing some shared data that should be cleared at the end of the
       
  1264       connection. Hooks and operations may put arbitrary data in there, and
       
  1265       this may also be used as a communication channel between the client and
       
  1266       the repository.
       
  1267 
       
  1268     .. automethod:: cubicweb.server.session.Session.get_shared_data
       
  1269     .. automethod:: cubicweb.server.session.Session.set_shared_data
       
  1270     .. automethod:: cubicweb.server.session.Session.added_in_transaction
       
  1271     .. automethod:: cubicweb.server.session.Session.deleted_in_transaction
       
  1272 
       
  1273     Connection state information:
       
  1274 
       
  1275       :attr:`running_dbapi_query`, boolean flag telling if the executing query
       
  1276       is coming from a dbapi connection or is a query from within the repository
       
  1277 
       
  1278       :attr:`cnxset`, the connections set to use to execute queries on sources.
       
  1279       During a transaction, the connection set may be freed so that is may be
       
  1280       used by another session as long as no writing is done. This means we can
       
  1281       have multiple sessions with a reasonably low connections set pool size.
       
  1282 
       
  1283       .. automethod:: cubicweb.server.session.Session.set_cnxset
       
  1284       .. automethod:: cubicweb.server.session.Session.free_cnxset
       
  1285 
       
  1286       :attr:`mode`, string telling the connections set handling mode, may be one
       
  1287       of 'read' (connections set may be freed), 'write' (some write was done in
       
  1288       the connections set, it can't be freed before end of the transaction),
       
  1289       'transaction' (we want to keep the connections set during all the
       
  1290       transaction, with or without writing)
       
  1291 
       
  1292       :attr:`pending_operations`, ordered list of operations to be processed on
       
  1293       commit/rollback
       
  1294 
       
  1295       :attr:`commit_state`, describing the transaction commit state, may be one
       
  1296       of None (not yet committing), 'precommit' (calling precommit event on
       
  1297       operations), 'postcommit' (calling postcommit event on operations),
       
  1298       'uncommitable' (some :exc:`ValidationError` or :exc:`Unauthorized` error
       
  1299       has been raised during the transaction and so it must be rolled back).
       
  1300 
       
  1301     .. automethod:: cubicweb.server.session.Session.commit
       
  1302     .. automethod:: cubicweb.server.session.Session.rollback
       
  1303     .. automethod:: cubicweb.server.session.Session.close
       
  1304     .. automethod:: cubicweb.server.session.Session.closed
       
  1305 
       
  1306     Security level Management:
       
  1307 
       
  1308       :attr:`read_security` and :attr:`write_security`, boolean flags telling if
       
  1309       read/write security is currently activated.
       
  1310 
       
  1311     .. automethod:: cubicweb.server.session.Session.security_enabled
       
  1312 
       
  1313     Hooks Management:
       
  1314 
       
  1315       :attr:`hooks_mode`, may be either `HOOKS_ALLOW_ALL` or `HOOKS_DENY_ALL`.
       
  1316 
       
  1317       :attr:`enabled_hook_categories`, when :attr:`hooks_mode` is
       
  1318       `HOOKS_DENY_ALL`, this set contains hooks categories that are enabled.
       
  1319 
       
  1320       :attr:`disabled_hook_categories`, when :attr:`hooks_mode` is
       
  1321       `HOOKS_ALLOW_ALL`, this set contains hooks categories that are disabled.
       
  1322 
       
  1323     .. automethod:: cubicweb.server.session.Session.deny_all_hooks_but
       
  1324     .. automethod:: cubicweb.server.session.Session.allow_all_hooks_but
       
  1325     .. automethod:: cubicweb.server.session.Session.is_hook_category_activated
       
  1326     .. automethod:: cubicweb.server.session.Session.is_hook_activated
       
  1327 
       
  1328     Data manipulation:
       
  1329 
       
  1330     .. automethod:: cubicweb.server.session.Session.add_relation
       
  1331     .. automethod:: cubicweb.server.session.Session.add_relations
       
  1332     .. automethod:: cubicweb.server.session.Session.delete_relation
       
  1333 
       
  1334     Other:
       
  1335 
       
  1336     .. automethod:: cubicweb.server.session.Session.call_service
       
  1337 
       
  1338 
       
  1339 
       
  1340     """
  1235     """
  1341     is_request = False
       
  1342 
  1236 
  1343     def __init__(self, user, repo, cnxprops=None, _id=None):
  1237     def __init__(self, user, repo, cnxprops=None, _id=None):
  1344         super(Session, self).__init__(repo.vreg)
       
  1345         self.sessionid = _id or make_uid(unormalize(user.login).encode('UTF8'))
  1238         self.sessionid = _id or make_uid(unormalize(user.login).encode('UTF8'))
  1346         self.user = user # XXX repoapi: deprecated and store only a login.
  1239         self.user = user # XXX repoapi: deprecated and store only a login.
  1347         self.repo = repo
  1240         self.repo = repo
       
  1241         self.vreg = repo.vreg
  1348         self._timestamp = Timestamp()
  1242         self._timestamp = Timestamp()
  1349         self.default_mode = 'read'
       
  1350         # short cut to querier .execute method
       
  1351         self._execute = repo.querier.execute
       
  1352         # shared data, used to communicate extra information between the client
       
  1353         # and the rql server
       
  1354         self.data = {}
  1243         self.data = {}
  1355         # i18n initialization
  1244         self.closed = False
  1356         self.set_language(user.prefered_language())
  1245 
  1357         ### internals
  1246     def close(self):
  1358         # Connection of this section
  1247         self.closed = True
  1359         self._cnxs = {} # XXX repoapi: remove this when nobody use the session
  1248 
  1360                         # as a Connection
  1249     def __enter__(self):
  1361         # Data local to the thread
  1250         return self
  1362         self.__threaddata = threading.local() # XXX repoapi: remove this when
  1251 
  1363                                               # nobody use the session as a Connection
  1252     def __exit__(self, *args):
  1364         self._cnxset_tracker = CnxSetTracker()
  1253         pass
  1365         self._closed = False
       
  1366         self._lock = threading.RLock()
       
  1367 
  1254 
  1368     def __unicode__(self):
  1255     def __unicode__(self):
  1369         return '<session %s (%s 0x%x)>' % (
  1256         return '<session %s (%s 0x%x)>' % (
  1370             unicode(self.user.login), self.sessionid, id(self))
  1257             unicode(self.user.login), self.sessionid, id(self))
       
  1258 
  1371     @property
  1259     @property
  1372     def timestamp(self):
  1260     def timestamp(self):
  1373         return float(self._timestamp)
  1261         return float(self._timestamp)
  1374 
  1262 
  1375     @property
  1263     @property
  1385         """Return a new Connection object linked to the session
  1273         """Return a new Connection object linked to the session
  1386 
  1274 
  1387         The returned Connection will *not* be managed by the Session.
  1275         The returned Connection will *not* be managed by the Session.
  1388         """
  1276         """
  1389         return Connection(self)
  1277         return Connection(self)
  1390 
       
  1391     def _get_cnx(self, cnxid):
       
  1392         """return the <cnxid> connection attached to this session
       
  1393 
       
  1394         Connection is created if necessary"""
       
  1395         with self._lock: # no connection exist with the same id
       
  1396             try:
       
  1397                 if self.closed:
       
  1398                     raise SessionClosedError('try to access connections set on'
       
  1399                                              ' a closed session %s' % self.id)
       
  1400                 cnx = self._cnxs[cnxid]
       
  1401                 assert cnx._session_handled
       
  1402             except KeyError:
       
  1403                 cnx = Connection(self, cnxid=cnxid, session_handled=True)
       
  1404                 self._cnxs[cnxid] = cnx
       
  1405                 cnx.__enter__()
       
  1406         return cnx
       
  1407 
       
  1408     def _close_cnx(self, cnx):
       
  1409         """Close a Connection related to a session"""
       
  1410         assert cnx._session_handled
       
  1411         cnx.__exit__()
       
  1412         self._cnxs.pop(cnx.connectionid, None)
       
  1413         try:
       
  1414             if self.__threaddata.cnx is cnx:
       
  1415                 del self.__threaddata.cnx
       
  1416         except AttributeError:
       
  1417             pass
       
  1418 
       
  1419     def set_cnx(self, cnxid=None):
       
  1420         # XXX repoapi: remove this when nobody use the session as a Connection
       
  1421         """set the default connection of the current thread to <cnxid>
       
  1422 
       
  1423         Connection is created if necessary"""
       
  1424         if cnxid is None:
       
  1425             cnxid = threading.currentThread().getName()
       
  1426         cnx = self._get_cnx(cnxid)
       
  1427         # New style session should not be accesed through the session.
       
  1428         assert cnx._session_handled
       
  1429         self.__threaddata.cnx = cnx
       
  1430 
       
  1431     @property
       
  1432     def _cnx(self):
       
  1433         """default connection for current session in current thread"""
       
  1434         try:
       
  1435             return self.__threaddata.cnx
       
  1436         except AttributeError:
       
  1437             self.set_cnx()
       
  1438             return self.__threaddata.cnx
       
  1439 
  1278 
  1440     @deprecated('[3.19] use a Connection object instead')
  1279     @deprecated('[3.19] use a Connection object instead')
  1441     def get_option_value(self, option, foreid=None):
  1280     def get_option_value(self, option, foreid=None):
  1442         if foreid is not None:
  1281         if foreid is not None:
  1443             warn('[3.19] foreid argument is deprecated', DeprecationWarning,
  1282             warn('[3.19] foreid argument is deprecated', DeprecationWarning,
  1444                  stacklevel=2)
  1283                  stacklevel=2)
  1445         return self.repo.get_option_value(option)
  1284         return self.repo.get_option_value(option)
  1446 
  1285 
  1447     @deprecated('[3.19] use a Connection object instead')
       
  1448     def transaction(self, free_cnxset=True):
       
  1449         """return context manager to enter a transaction for the session: when
       
  1450         exiting the `with` block on exception, call `session.rollback()`, else
       
  1451         call `session.commit()` on normal exit.
       
  1452 
       
  1453         The `free_cnxset` will be given to rollback/commit methods to indicate
       
  1454         whether the connections set should be freed or not.
       
  1455         """
       
  1456         return transaction(self, free_cnxset)
       
  1457 
       
  1458     add_relation = cnx_meth('add_relation')
       
  1459     add_relations = cnx_meth('add_relations')
       
  1460     delete_relation = cnx_meth('delete_relation')
       
  1461 
       
  1462     # relations cache handling #################################################
       
  1463 
       
  1464     update_rel_cache_add = cnx_meth('update_rel_cache_add')
       
  1465     update_rel_cache_del = cnx_meth('update_rel_cache_del')
       
  1466 
       
  1467     # resource accessors ######################################################
       
  1468 
       
  1469     system_sql = cnx_meth('system_sql')
       
  1470     deleted_in_transaction = cnx_meth('deleted_in_transaction')
       
  1471     added_in_transaction = cnx_meth('added_in_transaction')
       
  1472     rtype_eids_rdef = cnx_meth('rtype_eids_rdef')
       
  1473 
       
  1474     # security control #########################################################
       
  1475 
       
  1476     @deprecated('[3.19] use a Connection object instead')
       
  1477     def security_enabled(self, read=None, write=None):
       
  1478         return _session_security_enabled(self, read=read, write=write)
       
  1479 
       
  1480     read_security = cnx_attr('read_security', writable=True)
       
  1481     write_security = cnx_attr('write_security', writable=True)
       
  1482     running_dbapi_query = cnx_attr('running_dbapi_query')
       
  1483 
       
  1484     # hooks activation control #################################################
       
  1485     # all hooks should be activated during normal execution
       
  1486 
       
  1487 
       
  1488     @deprecated('[3.19] use a Connection object instead')
       
  1489     def allow_all_hooks_but(self, *categories):
       
  1490         return _session_hooks_control(self, HOOKS_ALLOW_ALL, *categories)
       
  1491     @deprecated('[3.19] use a Connection object instead')
       
  1492     def deny_all_hooks_but(self, *categories):
       
  1493         return _session_hooks_control(self, HOOKS_DENY_ALL, *categories)
       
  1494 
       
  1495     hooks_mode = cnx_attr('hooks_mode')
       
  1496 
       
  1497     disabled_hook_categories = cnx_attr('disabled_hook_cats')
       
  1498     enabled_hook_categories = cnx_attr('enabled_hook_cats')
       
  1499     disable_hook_categories = cnx_meth('disable_hook_categories')
       
  1500     enable_hook_categories = cnx_meth('enable_hook_categories')
       
  1501     is_hook_category_activated = cnx_meth('is_hook_category_activated')
       
  1502     is_hook_activated = cnx_meth('is_hook_activated')
       
  1503 
       
  1504     # connection management ###################################################
       
  1505 
       
  1506     @deprecated('[3.19] use a Connection object instead')
       
  1507     def keep_cnxset_mode(self, mode):
       
  1508         """set `mode`, e.g. how the session will keep its connections set:
       
  1509 
       
  1510         * if mode == 'write', the connections set is freed after each read
       
  1511           query, but kept until the transaction's end (eg commit or rollback)
       
  1512           when a write query is detected (eg INSERT/SET/DELETE queries)
       
  1513 
       
  1514         * if mode == 'transaction', the connections set is only freed after the
       
  1515           transaction's end
       
  1516 
       
  1517         notice that a repository has a limited set of connections sets, and a
       
  1518         session has to wait for a free connections set to run any rql query
       
  1519         (unless it already has one set).
       
  1520         """
       
  1521         assert mode in ('transaction', 'write')
       
  1522         if mode == 'transaction':
       
  1523             self.default_mode = 'transaction'
       
  1524         else: # mode == 'write'
       
  1525             self.default_mode = 'read'
       
  1526 
       
  1527     mode = cnx_attr('mode', writable=True)
       
  1528     commit_state = cnx_attr('commit_state', writable=True)
       
  1529 
       
  1530     @property
       
  1531     @deprecated('[3.19] use a Connection object instead')
       
  1532     def cnxset(self):
       
  1533         """connections set, set according to transaction mode for each query"""
       
  1534         if self._closed:
       
  1535             self.free_cnxset(True)
       
  1536             raise SessionClosedError('try to access connections set on a closed session %s' % self.id)
       
  1537         return self._cnx.cnxset
       
  1538 
       
  1539     def set_cnxset(self):
       
  1540         """the session need a connections set to execute some queries"""
       
  1541         with self._lock: # can probably be removed
       
  1542             if self._closed:
       
  1543                 self.free_cnxset(True)
       
  1544                 raise SessionClosedError('try to set connections set on a closed session %s' % self.id)
       
  1545             return self._cnx.set_cnxset()
       
  1546     free_cnxset = cnx_meth('free_cnxset')
       
  1547     ensure_cnx_set = cnx_attr('ensure_cnx_set')
       
  1548 
       
  1549     def _touch(self):
  1286     def _touch(self):
  1550         """update latest session usage timestamp and reset mode to read"""
  1287         """update latest session usage timestamp and reset mode to read"""
  1551         self._timestamp.touch()
  1288         self._timestamp.touch()
  1552 
  1289 
  1553     local_perm_cache = cnx_attr('local_perm_cache')
  1290     local_perm_cache = cnx_attr('local_perm_cache')
  1554     @local_perm_cache.setter
  1291     @local_perm_cache.setter
  1555     def local_perm_cache(self, value):
  1292     def local_perm_cache(self, value):
  1556         #base class assign an empty dict:-(
  1293         #base class assign an empty dict:-(
  1557         assert value == {}
  1294         assert value == {}
  1558         pass
  1295         pass
  1559 
       
  1560     # shared data handling ###################################################
       
  1561 
       
  1562     @deprecated('[3.19] use session or transaction data')
       
  1563     def get_shared_data(self, key, default=None, pop=False, txdata=False):
       
  1564         """return value associated to `key` in session data"""
       
  1565         if txdata:
       
  1566             return self._cnx.get_shared_data(key, default, pop, txdata=True)
       
  1567         else:
       
  1568             data = self.data
       
  1569         if pop:
       
  1570             return data.pop(key, default)
       
  1571         else:
       
  1572             return data.get(key, default)
       
  1573 
       
  1574     @deprecated('[3.19] use session or transaction data')
       
  1575     def set_shared_data(self, key, value, txdata=False):
       
  1576         """set value associated to `key` in session data"""
       
  1577         if txdata:
       
  1578             return self._cnx.set_shared_data(key, value, txdata=True)
       
  1579         else:
       
  1580             self.data[key] = value
       
  1581 
       
  1582     # server-side service call #################################################
       
  1583 
       
  1584     call_service = cnx_meth('call_service')
       
  1585 
       
  1586     # request interface #######################################################
       
  1587 
       
  1588     @property
       
  1589     @deprecated('[3.19] use a Connection object instead')
       
  1590     def cursor(self):
       
  1591         """return a rql cursor"""
       
  1592         return self
       
  1593 
       
  1594     set_entity_cache  = cnx_meth('set_entity_cache')
       
  1595     entity_cache      = cnx_meth('entity_cache')
       
  1596     cache_entities    = cnx_meth('cached_entities')
       
  1597     drop_entity_cache = cnx_meth('drop_entity_cache')
       
  1598 
       
  1599     source_defs = cnx_meth('source_defs')
       
  1600     entity_metas = cnx_meth('entity_metas')
       
  1601     describe = cnx_meth('describe') # XXX deprecated in 3.19
       
  1602 
       
  1603 
       
  1604     @deprecated('[3.19] use a Connection object instead')
       
  1605     def execute(self, *args, **kwargs):
       
  1606         """db-api like method directly linked to the querier execute method.
       
  1607 
       
  1608         See :meth:`cubicweb.dbapi.Cursor.execute` documentation.
       
  1609         """
       
  1610         rset = self._cnx.execute(*args, **kwargs)
       
  1611         rset.req = self
       
  1612         return rset
       
  1613 
       
  1614     def _clear_thread_data(self, free_cnxset=True):
       
  1615         """remove everything from the thread local storage, except connections set
       
  1616         which is explicitly removed by free_cnxset, and mode which is set anyway
       
  1617         by _touch
       
  1618         """
       
  1619         try:
       
  1620             cnx = self.__threaddata.cnx
       
  1621         except AttributeError:
       
  1622             pass
       
  1623         else:
       
  1624             if free_cnxset:
       
  1625                 cnx._free_cnxset()
       
  1626                 if cnx.ctx_count == 0:
       
  1627                     self._close_cnx(cnx)
       
  1628                 else:
       
  1629                     cnx.clear()
       
  1630             else:
       
  1631                 cnx.clear()
       
  1632 
       
  1633     @deprecated('[3.19] use a Connection object instead')
       
  1634     def commit(self, free_cnxset=True, reset_pool=None):
       
  1635         """commit the current session's transaction"""
       
  1636         cstate = self._cnx.commit_state
       
  1637         if cstate == 'uncommitable':
       
  1638             raise QueryError('transaction must be rolled back')
       
  1639         try:
       
  1640             return self._cnx.commit(free_cnxset, reset_pool)
       
  1641         finally:
       
  1642             self._clear_thread_data(free_cnxset)
       
  1643 
       
  1644     @deprecated('[3.19] use a Connection object instead')
       
  1645     def rollback(self, *args, **kwargs):
       
  1646         """rollback the current session's transaction"""
       
  1647         return self._rollback(*args, **kwargs)
       
  1648 
       
  1649     def _rollback(self, free_cnxset=True, **kwargs):
       
  1650         try:
       
  1651             return self._cnx.rollback(free_cnxset, **kwargs)
       
  1652         finally:
       
  1653             self._clear_thread_data(free_cnxset)
       
  1654 
       
  1655     def close(self):
       
  1656         # do not close connections set on session close, since they are shared now
       
  1657         tracker = self._cnxset_tracker
       
  1658         with self._lock:
       
  1659             self._closed = True
       
  1660         tracker.close()
       
  1661         if self._cnx._session_handled:
       
  1662             self._rollback()
       
  1663         self.debug('waiting for open connection of session: %s', self)
       
  1664         timeout = 10
       
  1665         pendings = tracker.wait(timeout)
       
  1666         if pendings:
       
  1667             self.error('%i connection still alive after 10 seconds, will close '
       
  1668                        'session anyway', len(pendings))
       
  1669             for cnxid in pendings:
       
  1670                 cnx = self._cnxs.get(cnxid)
       
  1671                 if cnx is not None:
       
  1672                     # drop cnx.cnxset
       
  1673                     with tracker:
       
  1674                         try:
       
  1675                             cnxset = cnx.cnxset
       
  1676                             if cnxset is None:
       
  1677                                 continue
       
  1678                             cnx.cnxset = None
       
  1679                         except RuntimeError:
       
  1680                             msg = 'issue while force free of cnxset in %s'
       
  1681                             self.error(msg, cnx)
       
  1682                     # cnxset.reconnect() do an hard reset of the cnxset
       
  1683                     # it force it to be freed
       
  1684                     cnxset.reconnect()
       
  1685                     self.repo._free_cnxset(cnxset)
       
  1686         del self.__threaddata
       
  1687         del self._cnxs
       
  1688 
       
  1689     @property
       
  1690     def closed(self):
       
  1691         return not hasattr(self, '_cnxs')
       
  1692 
       
  1693     # transaction data/operations management ##################################
       
  1694 
       
  1695     transaction_data = cnx_attr('transaction_data')
       
  1696     pending_operations = cnx_attr('pending_operations')
       
  1697     pruned_hooks_cache = cnx_attr('pruned_hooks_cache')
       
  1698     add_operation      = cnx_meth('add_operation')
       
  1699 
       
  1700     # undo support ############################################################
       
  1701 
       
  1702     ertype_supports_undo = cnx_meth('ertype_supports_undo')
       
  1703     transaction_inc_action_counter = cnx_meth('transaction_inc_action_counter')
       
  1704     transaction_uuid = cnx_meth('transaction_uuid')
       
  1705 
       
  1706     # querier helpers #########################################################
       
  1707 
       
  1708     rql_rewriter = cnx_attr('_rewriter')
       
  1709 
  1296 
  1710     # deprecated ###############################################################
  1297     # deprecated ###############################################################
  1711 
  1298 
  1712     @property
  1299     @property
  1713     def anonymous_session(self):
  1300     def anonymous_session(self):
  1721 
  1308 
  1722     @deprecated('[3.13] use getattr(session.rtype_eids_rdef(rtype, eidfrom, eidto), prop)')
  1309     @deprecated('[3.13] use getattr(session.rtype_eids_rdef(rtype, eidfrom, eidto), prop)')
  1723     def schema_rproperty(self, rtype, eidfrom, eidto, rprop):
  1310     def schema_rproperty(self, rtype, eidfrom, eidto, rprop):
  1724         return getattr(self.rtype_eids_rdef(rtype, eidfrom, eidto), rprop)
  1311         return getattr(self.rtype_eids_rdef(rtype, eidfrom, eidto), rprop)
  1725 
  1312 
  1726     @property
       
  1727     @deprecated("[3.13] use .cnxset attribute instead of .pool")
       
  1728     def pool(self):
       
  1729         return self.cnxset
       
  1730 
       
  1731     @deprecated("[3.13] use .set_cnxset() method instead of .set_pool()")
       
  1732     def set_pool(self):
       
  1733         return self.set_cnxset()
       
  1734 
       
  1735     @deprecated("[3.13] use .free_cnxset() method instead of .reset_pool()")
       
  1736     def reset_pool(self):
       
  1737         return self.free_cnxset()
       
  1738 
       
  1739     # these are overridden by set_log_methods below
  1313     # these are overridden by set_log_methods below
  1740     # only defining here to prevent pylint from complaining
  1314     # only defining here to prevent pylint from complaining
  1741     info = warning = error = critical = exception = debug = lambda msg,*a,**kw: None
  1315     info = warning = error = critical = exception = debug = lambda msg,*a,**kw: None
  1742 
  1316 
  1743 Session.HOOKS_ALLOW_ALL = HOOKS_ALLOW_ALL
       
  1744 Session.HOOKS_DENY_ALL = HOOKS_DENY_ALL
       
  1745 Session.DEFAULT_SECURITY = DEFAULT_SECURITY
       
  1746 
  1317 
  1747 
  1318 
  1748 class InternalManager(object):
  1319 class InternalManager(object):
  1749     """a manager user with all access rights used internally for task such as
  1320     """a manager user with all access rights used internally for task such as
  1750     bootstrapping the repository or creating regular users according to
  1321     bootstrapping the repository or creating regular users according to