[repoapi,session] remove all session-as-cnx backward compat

The dbapi being gone, we now can drop the session object bw-compatibility layer. This will allow further simplifications, such as folding ClientConnection and Connection (without too much pain), and then having persistent sessions.

Related to #3933480.

authorAurelien Campeas <aurelien.campeas@logilab.fr>
changesetb926ff4ef4a8
branchdefault
phasepublic
hiddenno
parent revision#ef54ea75a642 [server] drop repo.internal_session and InternalSession
child revision#52a976c5d27a [connection] provide some missing documentation bits
files modified by this revision
devtools/testlib.py
server/migractions.py
server/repository.py
server/session.py
server/test/unittest_repository.py
server/test/unittest_session.py
# HG changeset patch
# User Aurelien Campeas <aurelien.campeas@logilab.fr>
# Date 1402067288 -7200
# Fri Jun 06 17:08:08 2014 +0200
# Node ID b926ff4ef4a8ab3c647d96f8274a11099a9b9e11
# Parent ef54ea75a642dce3db198b2d29cb31407b6778cb
[repoapi,session] remove all session-as-cnx backward compat

The `dbapi` being gone, we now can drop the session object
bw-compatibility layer. This will allow further simplifications, such
as folding ClientConnection and Connection (without too much pain),
and then having persistent sessions.

Related to #3933480.

diff --git a/devtools/testlib.py b/devtools/testlib.py
@@ -356,23 +356,13 @@
1 
2      @property
3      @deprecated('[3.19] explicitly use RepoAccess object in test instead')
4      def session(self):
5          """return current server side session"""
6 -        # XXX We want to use a srv_connection instead and deprecate this
7 -        # property
8          session = self._current_session
9          if session is None:
10              session = self._admin_session
11 -            # bypassing all sanity to use the same repo cnx in the session
12 -            #
13 -            # we can't call set_cnx as the Connection is not managed by the
14 -            # session.
15 -            session._Session__threaddata.cnx = self._admin_clt_cnx._cnx
16 -        else:
17 -            session._Session__threaddata.cnx = self.cnx._cnx
18 -        session.set_cnxset()
19          return session
20 
21      @property
22      @deprecated('[3.19] explicitly use RepoAccess object in test instead')
23      def websession(self):
@@ -540,12 +530,11 @@
24          if self._admin_clt_cnx is not None:
25              if self._admin_clt_cnx._open:
26                  self._admin_clt_cnx.close()
27              self._admin_clt_cnx = None
28          if self._admin_session is not None:
29 -            if not self._admin_session.closed:
30 -                self.repo.close(self._admin_session.sessionid)
31 +            self.repo.close(self._admin_session.sessionid)
32              self._admin_session = None
33          while self._cleanups:
34              cleanup, args, kwargs = self._cleanups.pop(-1)
35              cleanup(*args, **kwargs)
36          self.repo.turn_repo_off()
diff --git a/server/migractions.py b/server/migractions.py
@@ -95,11 +95,11 @@
37              self.cnx = cnx
38              self.repo = repo
39              self.session = cnx._session
40          elif connect:
41              self.repo_connect()
42 -            self.set_session()
43 +            self.set_cnx()
44          else:
45              self.session = None
46          # no config on shell to a remote instance
47          if config is not None and (cnx or connect):
48              repo = self.repo
@@ -123,11 +123,11 @@
49                  if insert_lperms:
50                      config._cubes = cubes
51          self.fs_schema = schema
52          self._synchronized = set()
53 
54 -    def set_session(self):
55 +    def set_cnx(self):
56          try:
57              login = self.repo.config.default_admin_config['login']
58              pwd = self.repo.config.default_admin_config['password']
59          except KeyError:
60              login, pwd = manager_userpasswd()
@@ -147,11 +147,10 @@
61                  login, pwd = manager_userpasswd()
62              except (KeyboardInterrupt, EOFError):
63                  print 'aborting...'
64                  sys.exit(0)
65          self.session = self.repo._get_session(self.cnx.sessionid)
66 -        self.session.keep_cnxset_mode('transaction')
67 
68      # overriden from base MigrationHelper ######################################
69 
70      @cached
71      def repo_connect(self):
diff --git a/server/repository.py b/server/repository.py
@@ -666,19 +666,17 @@
72 
73      def check_session(self, sessionid):
74          """raise `BadConnectionId` if the connection is no more valid, else
75          return its latest activity timestamp.
76          """
77 -        return self._get_session(sessionid, setcnxset=False).timestamp
78 +        return self._get_session(sessionid).timestamp
79 
80      def close(self, sessionid, txid=None, checkshuttingdown=True):
81          """close the session with the given id"""
82          session = self._get_session(sessionid, txid=txid,
83                                      checkshuttingdown=checkshuttingdown)
84          # operation uncommited before close are rolled back before hook is called
85 -        if session._cnx._session_handled:
86 -            session._cnx.rollback(free_cnxset=False)
87          with session.new_cnx() as cnx:
88              self.hm.call_hooks('session_close', cnx)
89              # commit connection at this point in case write operation has been
90              # done during `session_close` hooks
91              cnx.commit()
@@ -722,22 +720,18 @@
92              with session.new_cnx() as cnx:
93                  with cnx.security_enabled(read=False, write=False):
94                      with cnx.ensure_cnx_set:
95                          yield cnx
96 
97 -    def _get_session(self, sessionid, setcnxset=False, txid=None,
98 -                     checkshuttingdown=True):
99 +    def _get_session(self, sessionid, txid=None, checkshuttingdown=True):
100          """return the session associated with the given session identifier"""
101          if checkshuttingdown and self.shutting_down:
102              raise ShuttingDown('Repository is shutting down')
103          try:
104              session = self._sessions[sessionid]
105          except KeyError:
106              raise BadConnectionId('No such session %s' % sessionid)
107 -        if setcnxset:
108 -            session.set_cnx(txid) # must be done before set_cnxset
109 -            session.set_cnxset()
110          return session
111 
112      # data sources handling ###################################################
113      # * correspondance between eid and (type, source)
114      # * correspondance between eid and local id (i.e. specific to a given source)
diff --git a/server/session.py b/server/session.py
@@ -437,10 +437,11 @@
115        read/write security is currently activated.
116 
117      """
118 
119      is_request = False
120 +    mode = 'read'
121 
122      def __init__(self, session, cnxid=None, session_handled=False):
123          # using super(Connection, self) confuse some test hack
124          RequestSessionBase.__init__(self, session.vreg)
125          # only the session provide explicite
@@ -471,16 +472,14 @@
126          self._execute = self.repo.querier.execute
127 
128          # other session utility
129          self._session_timestamp = session._timestamp
130 
131 -        #: connection handling mode
132 -        self.mode = session.default_mode
133          #: connection set used to execute queries on sources
134          self._cnxset = None
135          #: CnxSetTracker used to report cnxset usage
136 -        self._cnxset_tracker = session._cnxset_tracker
137 +        self._cnxset_tracker = CnxSetTracker()
138          #: is this connection from a client or internal to the repo
139          self.running_dbapi_query = True
140          # internal (root) session
141          self.is_internal_session = isinstance(session.user, InternalManager)
142 
@@ -1224,152 +1223,41 @@
143 
144      def __float__(self):
145          return float(self.value)
146 
147 
148 -class Session(RequestSessionBase): # XXX repoapi: stop being a
149 -                                   # RequestSessionBase at some point
150 +class Session(object):
151      """Repository user session
152 
153      This ties all together:
154       * session id,
155       * user,
156 -     * connections set,
157       * other session data.
158 -
159 -    **About session storage / transactions**
160 -
161 -    Here is a description of internal session attributes. Besides :attr:`data`
162 -    and :attr:`transaction_data`, you should not have to use attributes
163 -    described here but higher level APIs.
164 -
165 -      :attr:`data` is a dictionary containing shared data, used to communicate
166 -      extra information between the client and the repository
167 -
168 -      :attr:`_cnxs` is a dictionary of :class:`Connection` instance, one
169 -      for each running connection. The key is the connection id. By default
170 -      the connection id is the thread name but it can be otherwise (per dbapi
171 -      cursor for instance, or per thread name *from another process*).
172 -
173 -      :attr:`__threaddata` is a thread local storage whose `cnx` attribute
174 -      refers to the proper instance of :class:`Connection` according to the
175 -      connection.
176 -
177 -    You should not have to use neither :attr:`_cnx` nor :attr:`__threaddata`,
178 -    simply access connection data transparently through the :attr:`_cnx`
179 -    property. Also, you usually don't have to access it directly since current
180 -    connection's data may be accessed/modified through properties / methods:
181 -
182 -      :attr:`connection_data`, similarly to :attr:`data`, is a dictionary
183 -      containing some shared data that should be cleared at the end of the
184 -      connection. Hooks and operations may put arbitrary data in there, and
185 -      this may also be used as a communication channel between the client and
186 -      the repository.
187 -
188 -    .. automethod:: cubicweb.server.session.Session.get_shared_data
189 -    .. automethod:: cubicweb.server.session.Session.set_shared_data
190 -    .. automethod:: cubicweb.server.session.Session.added_in_transaction
191 -    .. automethod:: cubicweb.server.session.Session.deleted_in_transaction
192 -
193 -    Connection state information:
194 -
195 -      :attr:`running_dbapi_query`, boolean flag telling if the executing query
196 -      is coming from a dbapi connection or is a query from within the repository
197 -
198 -      :attr:`cnxset`, the connections set to use to execute queries on sources.
199 -      During a transaction, the connection set may be freed so that is may be
200 -      used by another session as long as no writing is done. This means we can
201 -      have multiple sessions with a reasonably low connections set pool size.
202 -
203 -      .. automethod:: cubicweb.server.session.Session.set_cnxset
204 -      .. automethod:: cubicweb.server.session.Session.free_cnxset
205 -
206 -      :attr:`mode`, string telling the connections set handling mode, may be one
207 -      of 'read' (connections set may be freed), 'write' (some write was done in
208 -      the connections set, it can't be freed before end of the transaction),
209 -      'transaction' (we want to keep the connections set during all the
210 -      transaction, with or without writing)
211 -
212 -      :attr:`pending_operations`, ordered list of operations to be processed on
213 -      commit/rollback
214 -
215 -      :attr:`commit_state`, describing the transaction commit state, may be one
216 -      of None (not yet committing), 'precommit' (calling precommit event on
217 -      operations), 'postcommit' (calling postcommit event on operations),
218 -      'uncommitable' (some :exc:`ValidationError` or :exc:`Unauthorized` error
219 -      has been raised during the transaction and so it must be rolled back).
220 -
221 -    .. automethod:: cubicweb.server.session.Session.commit
222 -    .. automethod:: cubicweb.server.session.Session.rollback
223 -    .. automethod:: cubicweb.server.session.Session.close
224 -    .. automethod:: cubicweb.server.session.Session.closed
225 -
226 -    Security level Management:
227 -
228 -      :attr:`read_security` and :attr:`write_security`, boolean flags telling if
229 -      read/write security is currently activated.
230 -
231 -    .. automethod:: cubicweb.server.session.Session.security_enabled
232 -
233 -    Hooks Management:
234 -
235 -      :attr:`hooks_mode`, may be either `HOOKS_ALLOW_ALL` or `HOOKS_DENY_ALL`.
236 -
237 -      :attr:`enabled_hook_categories`, when :attr:`hooks_mode` is
238 -      `HOOKS_DENY_ALL`, this set contains hooks categories that are enabled.
239 -
240 -      :attr:`disabled_hook_categories`, when :attr:`hooks_mode` is
241 -      `HOOKS_ALLOW_ALL`, this set contains hooks categories that are disabled.
242 -
243 -    .. automethod:: cubicweb.server.session.Session.deny_all_hooks_but
244 -    .. automethod:: cubicweb.server.session.Session.allow_all_hooks_but
245 -    .. automethod:: cubicweb.server.session.Session.is_hook_category_activated
246 -    .. automethod:: cubicweb.server.session.Session.is_hook_activated
247 -
248 -    Data manipulation:
249 -
250 -    .. automethod:: cubicweb.server.session.Session.add_relation
251 -    .. automethod:: cubicweb.server.session.Session.add_relations
252 -    .. automethod:: cubicweb.server.session.Session.delete_relation
253 -
254 -    Other:
255 -
256 -    .. automethod:: cubicweb.server.session.Session.call_service
257 -
258 -
259 -
260      """
261 -    is_request = False
262 
263      def __init__(self, user, repo, cnxprops=None, _id=None):
264 -        super(Session, self).__init__(repo.vreg)
265          self.sessionid = _id or make_uid(unormalize(user.login).encode('UTF8'))
266          self.user = user # XXX repoapi: deprecated and store only a login.
267          self.repo = repo
268 +        self.vreg = repo.vreg
269          self._timestamp = Timestamp()
270 -        self.default_mode = 'read'
271 -        # short cut to querier .execute method
272 -        self._execute = repo.querier.execute
273 -        # shared data, used to communicate extra information between the client
274 -        # and the rql server
275          self.data = {}
276 -        # i18n initialization
277 -        self.set_language(user.prefered_language())
278 -        ### internals
279 -        # Connection of this section
280 -        self._cnxs = {} # XXX repoapi: remove this when nobody use the session
281 -                        # as a Connection
282 -        # Data local to the thread
283 -        self.__threaddata = threading.local() # XXX repoapi: remove this when
284 -                                              # nobody use the session as a Connection
285 -        self._cnxset_tracker = CnxSetTracker()
286 -        self._closed = False
287 -        self._lock = threading.RLock()
288 +        self.closed = False
289 +
290 +    def close(self):
291 +        self.closed = True
292 +
293 +    def __enter__(self):
294 +        return self
295 +
296 +    def __exit__(self, *args):
297 +        pass
298 
299      def __unicode__(self):
300          return '<session %s (%s 0x%x)>' % (
301              unicode(self.user.login), self.sessionid, id(self))
302 +
303      @property
304      def timestamp(self):
305          return float(self._timestamp)
306 
307      @property
@@ -1386,168 +1274,17 @@
308 
309          The returned Connection will *not* be managed by the Session.
310          """
311          return Connection(self)
312 
313 -    def _get_cnx(self, cnxid):
314 -        """return the <cnxid> connection attached to this session
315 -
316 -        Connection is created if necessary"""
317 -        with self._lock: # no connection exist with the same id
318 -            try:
319 -                if self.closed:
320 -                    raise SessionClosedError('try to access connections set on'
321 -                                             ' a closed session %s' % self.id)
322 -                cnx = self._cnxs[cnxid]
323 -                assert cnx._session_handled
324 -            except KeyError:
325 -                cnx = Connection(self, cnxid=cnxid, session_handled=True)
326 -                self._cnxs[cnxid] = cnx
327 -                cnx.__enter__()
328 -        return cnx
329 -
330 -    def _close_cnx(self, cnx):
331 -        """Close a Connection related to a session"""
332 -        assert cnx._session_handled
333 -        cnx.__exit__()
334 -        self._cnxs.pop(cnx.connectionid, None)
335 -        try:
336 -            if self.__threaddata.cnx is cnx:
337 -                del self.__threaddata.cnx
338 -        except AttributeError:
339 -            pass
340 -
341 -    def set_cnx(self, cnxid=None):
342 -        # XXX repoapi: remove this when nobody use the session as a Connection
343 -        """set the default connection of the current thread to <cnxid>
344 -
345 -        Connection is created if necessary"""
346 -        if cnxid is None:
347 -            cnxid = threading.currentThread().getName()
348 -        cnx = self._get_cnx(cnxid)
349 -        # New style session should not be accesed through the session.
350 -        assert cnx._session_handled
351 -        self.__threaddata.cnx = cnx
352 -
353 -    @property
354 -    def _cnx(self):
355 -        """default connection for current session in current thread"""
356 -        try:
357 -            return self.__threaddata.cnx
358 -        except AttributeError:
359 -            self.set_cnx()
360 -            return self.__threaddata.cnx
361 -
362      @deprecated('[3.19] use a Connection object instead')
363      def get_option_value(self, option, foreid=None):
364          if foreid is not None:
365              warn('[3.19] foreid argument is deprecated', DeprecationWarning,
366                   stacklevel=2)
367          return self.repo.get_option_value(option)
368 
369 -    @deprecated('[3.19] use a Connection object instead')
370 -    def transaction(self, free_cnxset=True):
371 -        """return context manager to enter a transaction for the session: when
372 -        exiting the `with` block on exception, call `session.rollback()`, else
373 -        call `session.commit()` on normal exit.
374 -
375 -        The `free_cnxset` will be given to rollback/commit methods to indicate
376 -        whether the connections set should be freed or not.
377 -        """
378 -        return transaction(self, free_cnxset)
379 -
380 -    add_relation = cnx_meth('add_relation')
381 -    add_relations = cnx_meth('add_relations')
382 -    delete_relation = cnx_meth('delete_relation')
383 -
384 -    # relations cache handling #################################################
385 -
386 -    update_rel_cache_add = cnx_meth('update_rel_cache_add')
387 -    update_rel_cache_del = cnx_meth('update_rel_cache_del')
388 -
389 -    # resource accessors ######################################################
390 -
391 -    system_sql = cnx_meth('system_sql')
392 -    deleted_in_transaction = cnx_meth('deleted_in_transaction')
393 -    added_in_transaction = cnx_meth('added_in_transaction')
394 -    rtype_eids_rdef = cnx_meth('rtype_eids_rdef')
395 -
396 -    # security control #########################################################
397 -
398 -    @deprecated('[3.19] use a Connection object instead')
399 -    def security_enabled(self, read=None, write=None):
400 -        return _session_security_enabled(self, read=read, write=write)
401 -
402 -    read_security = cnx_attr('read_security', writable=True)
403 -    write_security = cnx_attr('write_security', writable=True)
404 -    running_dbapi_query = cnx_attr('running_dbapi_query')
405 -
406 -    # hooks activation control #################################################
407 -    # all hooks should be activated during normal execution
408 -
409 -
410 -    @deprecated('[3.19] use a Connection object instead')
411 -    def allow_all_hooks_but(self, *categories):
412 -        return _session_hooks_control(self, HOOKS_ALLOW_ALL, *categories)
413 -    @deprecated('[3.19] use a Connection object instead')
414 -    def deny_all_hooks_but(self, *categories):
415 -        return _session_hooks_control(self, HOOKS_DENY_ALL, *categories)
416 -
417 -    hooks_mode = cnx_attr('hooks_mode')
418 -
419 -    disabled_hook_categories = cnx_attr('disabled_hook_cats')
420 -    enabled_hook_categories = cnx_attr('enabled_hook_cats')
421 -    disable_hook_categories = cnx_meth('disable_hook_categories')
422 -    enable_hook_categories = cnx_meth('enable_hook_categories')
423 -    is_hook_category_activated = cnx_meth('is_hook_category_activated')
424 -    is_hook_activated = cnx_meth('is_hook_activated')
425 -
426 -    # connection management ###################################################
427 -
428 -    @deprecated('[3.19] use a Connection object instead')
429 -    def keep_cnxset_mode(self, mode):
430 -        """set `mode`, e.g. how the session will keep its connections set:
431 -
432 -        * if mode == 'write', the connections set is freed after each read
433 -          query, but kept until the transaction's end (eg commit or rollback)
434 -          when a write query is detected (eg INSERT/SET/DELETE queries)
435 -
436 -        * if mode == 'transaction', the connections set is only freed after the
437 -          transaction's end
438 -
439 -        notice that a repository has a limited set of connections sets, and a
440 -        session has to wait for a free connections set to run any rql query
441 -        (unless it already has one set).
442 -        """
443 -        assert mode in ('transaction', 'write')
444 -        if mode == 'transaction':
445 -            self.default_mode = 'transaction'
446 -        else: # mode == 'write'
447 -            self.default_mode = 'read'
448 -
449 -    mode = cnx_attr('mode', writable=True)
450 -    commit_state = cnx_attr('commit_state', writable=True)
451 -
452 -    @property
453 -    @deprecated('[3.19] use a Connection object instead')
454 -    def cnxset(self):
455 -        """connections set, set according to transaction mode for each query"""
456 -        if self._closed:
457 -            self.free_cnxset(True)
458 -            raise SessionClosedError('try to access connections set on a closed session %s' % self.id)
459 -        return self._cnx.cnxset
460 -
461 -    def set_cnxset(self):
462 -        """the session need a connections set to execute some queries"""
463 -        with self._lock: # can probably be removed
464 -            if self._closed:
465 -                self.free_cnxset(True)
466 -                raise SessionClosedError('try to set connections set on a closed session %s' % self.id)
467 -            return self._cnx.set_cnxset()
468 -    free_cnxset = cnx_meth('free_cnxset')
469 -    ensure_cnx_set = cnx_attr('ensure_cnx_set')
470 -
471      def _touch(self):
472          """update latest session usage timestamp and reset mode to read"""
473          self._timestamp.touch()
474 
475      local_perm_cache = cnx_attr('local_perm_cache')
@@ -1555,160 +1292,10 @@
476      def local_perm_cache(self, value):
477          #base class assign an empty dict:-(
478          assert value == {}
479          pass
480 
481 -    # shared data handling ###################################################
482 -
483 -    @deprecated('[3.19] use session or transaction data')
484 -    def get_shared_data(self, key, default=None, pop=False, txdata=False):
485 -        """return value associated to `key` in session data"""
486 -        if txdata:
487 -            return self._cnx.get_shared_data(key, default, pop, txdata=True)
488 -        else:
489 -            data = self.data
490 -        if pop:
491 -            return data.pop(key, default)
492 -        else:
493 -            return data.get(key, default)
494 -
495 -    @deprecated('[3.19] use session or transaction data')
496 -    def set_shared_data(self, key, value, txdata=False):
497 -        """set value associated to `key` in session data"""
498 -        if txdata:
499 -            return self._cnx.set_shared_data(key, value, txdata=True)
500 -        else:
501 -            self.data[key] = value
502 -
503 -    # server-side service call #################################################
504 -
505 -    call_service = cnx_meth('call_service')
506 -
507 -    # request interface #######################################################
508 -
509 -    @property
510 -    @deprecated('[3.19] use a Connection object instead')
511 -    def cursor(self):
512 -        """return a rql cursor"""
513 -        return self
514 -
515 -    set_entity_cache  = cnx_meth('set_entity_cache')
516 -    entity_cache      = cnx_meth('entity_cache')
517 -    cache_entities    = cnx_meth('cached_entities')
518 -    drop_entity_cache = cnx_meth('drop_entity_cache')
519 -
520 -    source_defs = cnx_meth('source_defs')
521 -    entity_metas = cnx_meth('entity_metas')
522 -    describe = cnx_meth('describe') # XXX deprecated in 3.19
523 -
524 -
525 -    @deprecated('[3.19] use a Connection object instead')
526 -    def execute(self, *args, **kwargs):
527 -        """db-api like method directly linked to the querier execute method.
528 -
529 -        See :meth:`cubicweb.dbapi.Cursor.execute` documentation.
530 -        """
531 -        rset = self._cnx.execute(*args, **kwargs)
532 -        rset.req = self
533 -        return rset
534 -
535 -    def _clear_thread_data(self, free_cnxset=True):
536 -        """remove everything from the thread local storage, except connections set
537 -        which is explicitly removed by free_cnxset, and mode which is set anyway
538 -        by _touch
539 -        """
540 -        try:
541 -            cnx = self.__threaddata.cnx
542 -        except AttributeError:
543 -            pass
544 -        else:
545 -            if free_cnxset:
546 -                cnx._free_cnxset()
547 -                if cnx.ctx_count == 0:
548 -                    self._close_cnx(cnx)
549 -                else:
550 -                    cnx.clear()
551 -            else:
552 -                cnx.clear()
553 -
554 -    @deprecated('[3.19] use a Connection object instead')
555 -    def commit(self, free_cnxset=True, reset_pool=None):
556 -        """commit the current session's transaction"""
557 -        cstate = self._cnx.commit_state
558 -        if cstate == 'uncommitable':
559 -            raise QueryError('transaction must be rolled back')
560 -        try:
561 -            return self._cnx.commit(free_cnxset, reset_pool)
562 -        finally:
563 -            self._clear_thread_data(free_cnxset)
564 -
565 -    @deprecated('[3.19] use a Connection object instead')
566 -    def rollback(self, *args, **kwargs):
567 -        """rollback the current session's transaction"""
568 -        return self._rollback(*args, **kwargs)
569 -
570 -    def _rollback(self, free_cnxset=True, **kwargs):
571 -        try:
572 -            return self._cnx.rollback(free_cnxset, **kwargs)
573 -        finally:
574 -            self._clear_thread_data(free_cnxset)
575 -
576 -    def close(self):
577 -        # do not close connections set on session close, since they are shared now
578 -        tracker = self._cnxset_tracker
579 -        with self._lock:
580 -            self._closed = True
581 -        tracker.close()
582 -        if self._cnx._session_handled:
583 -            self._rollback()
584 -        self.debug('waiting for open connection of session: %s', self)
585 -        timeout = 10
586 -        pendings = tracker.wait(timeout)
587 -        if pendings:
588 -            self.error('%i connection still alive after 10 seconds, will close '
589 -                       'session anyway', len(pendings))
590 -            for cnxid in pendings:
591 -                cnx = self._cnxs.get(cnxid)
592 -                if cnx is not None:
593 -                    # drop cnx.cnxset
594 -                    with tracker:
595 -                        try:
596 -                            cnxset = cnx.cnxset
597 -                            if cnxset is None:
598 -                                continue
599 -                            cnx.cnxset = None
600 -                        except RuntimeError:
601 -                            msg = 'issue while force free of cnxset in %s'
602 -                            self.error(msg, cnx)
603 -                    # cnxset.reconnect() do an hard reset of the cnxset
604 -                    # it force it to be freed
605 -                    cnxset.reconnect()
606 -                    self.repo._free_cnxset(cnxset)
607 -        del self.__threaddata
608 -        del self._cnxs
609 -
610 -    @property
611 -    def closed(self):
612 -        return not hasattr(self, '_cnxs')
613 -
614 -    # transaction data/operations management ##################################
615 -
616 -    transaction_data = cnx_attr('transaction_data')
617 -    pending_operations = cnx_attr('pending_operations')
618 -    pruned_hooks_cache = cnx_attr('pruned_hooks_cache')
619 -    add_operation      = cnx_meth('add_operation')
620 -
621 -    # undo support ############################################################
622 -
623 -    ertype_supports_undo = cnx_meth('ertype_supports_undo')
624 -    transaction_inc_action_counter = cnx_meth('transaction_inc_action_counter')
625 -    transaction_uuid = cnx_meth('transaction_uuid')
626 -
627 -    # querier helpers #########################################################
628 -
629 -    rql_rewriter = cnx_attr('_rewriter')
630 -
631      # deprecated ###############################################################
632 
633      @property
634      def anonymous_session(self):
635          # XXX for now, anonymous_user only exists in webconfig (and testconfig).
@@ -1721,30 +1308,14 @@
636 
637      @deprecated('[3.13] use getattr(session.rtype_eids_rdef(rtype, eidfrom, eidto), prop)')
638      def schema_rproperty(self, rtype, eidfrom, eidto, rprop):
639          return getattr(self.rtype_eids_rdef(rtype, eidfrom, eidto), rprop)
640 
641 -    @property
642 -    @deprecated("[3.13] use .cnxset attribute instead of .pool")
643 -    def pool(self):
644 -        return self.cnxset
645 -
646 -    @deprecated("[3.13] use .set_cnxset() method instead of .set_pool()")
647 -    def set_pool(self):
648 -        return self.set_cnxset()
649 -
650 -    @deprecated("[3.13] use .free_cnxset() method instead of .reset_pool()")
651 -    def reset_pool(self):
652 -        return self.free_cnxset()
653 -
654      # these are overridden by set_log_methods below
655      # only defining here to prevent pylint from complaining
656      info = warning = error = critical = exception = debug = lambda msg,*a,**kw: None
657 
658 -Session.HOOKS_ALLOW_ALL = HOOKS_ALLOW_ALL
659 -Session.HOOKS_DENY_ALL = HOOKS_DENY_ALL
660 -Session.DEFAULT_SECURITY = DEFAULT_SECURITY
661 
662 
663  class InternalManager(object):
664      """a manager user with all access rights used internally for task such as
665      bootstrapping the repository or creating regular users according to
diff --git a/server/test/unittest_repository.py b/server/test/unittest_repository.py
@@ -199,14 +199,16 @@
666          self.assertEqual(ownedby.objects('CWEType'), ('CWUser',))
667 
668      def test_internal_api(self):
669          repo = self.repo
670          cnxid = repo.connect(self.admlogin, password=self.admpassword)
671 -        session = repo._get_session(cnxid, setcnxset=True)
672 -        self.assertEqual(repo.type_and_source_from_eid(2, session),
673 -                         ('CWGroup', None, 'system'))
674 -        self.assertEqual(repo.type_from_eid(2, session), 'CWGroup')
675 +        session = repo._get_session(cnxid)
676 +        with session.new_cnx() as cnx:
677 +            with cnx.ensure_cnx_set:
678 +                self.assertEqual(repo.type_and_source_from_eid(2, cnx),
679 +                                 ('CWGroup', None, 'system'))
680 +                self.assertEqual(repo.type_from_eid(2, cnx), 'CWGroup')
681          repo.close(cnxid)
682 
683      def test_public_api(self):
684          self.assertEqual(self.repo.get_schema(), self.repo.schema)
685          self.assertEqual(self.repo.source_defs(), {'system': {'type': 'native',
diff --git a/server/test/unittest_session.py b/server/test/unittest_session.py
@@ -1,108 +0,0 @@
686 -# copyright 2003-2014 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
687 -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
688 -#
689 -# This file is part of CubicWeb.
690 -#
691 -# CubicWeb is free software: you can redistribute it and/or modify it under the
692 -# terms of the GNU Lesser General Public License as published by the Free
693 -# Software Foundation, either version 2.1 of the License, or (at your option)
694 -# any later version.
695 -#
696 -# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
697 -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
698 -# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
699 -# details.
700 -#
701 -# You should have received a copy of the GNU Lesser General Public License along
702 -# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
703 -
704 -from cubicweb.devtools.testlib import CubicWebTC
705 -from cubicweb.server.session import HOOKS_ALLOW_ALL, HOOKS_DENY_ALL
706 -from cubicweb.server import hook
707 -from cubicweb.predicates import is_instance
708 -
709 -class SessionTC(CubicWebTC):
710 -
711 -    def test_hooks_control(self):
712 -        session = self.session
713 -        # this test check the "old" behavior of session with automatic connection management
714 -        # close the default cnx, we do nto want it to interfer with the test
715 -        self.cnx.close()
716 -        # open a dedicated one
717 -        session.set_cnx('Some-random-cnx-unrelated-to-the-default-one')
718 -        # go test go
719 -        self.assertEqual(HOOKS_ALLOW_ALL, session.hooks_mode)
720 -        self.assertEqual(set(), session.disabled_hook_categories)
721 -        self.assertEqual(set(), session.enabled_hook_categories)
722 -        self.assertEqual(1, len(session._cnxs))
723 -        with session.deny_all_hooks_but('metadata'):
724 -            self.assertEqual(HOOKS_DENY_ALL, session.hooks_mode)
725 -            self.assertEqual(set(), session.disabled_hook_categories)
726 -            self.assertEqual(set(('metadata',)), session.enabled_hook_categories)
727 -            session.commit()
728 -            self.assertEqual(HOOKS_DENY_ALL, session.hooks_mode)
729 -            self.assertEqual(set(), session.disabled_hook_categories)
730 -            self.assertEqual(set(('metadata',)), session.enabled_hook_categories)
731 -            session.rollback()
732 -            self.assertEqual(HOOKS_DENY_ALL, session.hooks_mode)
733 -            self.assertEqual(set(), session.disabled_hook_categories)
734 -            self.assertEqual(set(('metadata',)), session.enabled_hook_categories)
735 -            with session.allow_all_hooks_but('integrity'):
736 -                self.assertEqual(HOOKS_ALLOW_ALL, session.hooks_mode)
737 -                self.assertEqual(set(('integrity',)), session.disabled_hook_categories)
738 -                self.assertEqual(set(('metadata',)), session.enabled_hook_categories) # not changed in such case
739 -            self.assertEqual(HOOKS_DENY_ALL, session.hooks_mode)
740 -            self.assertEqual(set(), session.disabled_hook_categories)
741 -            self.assertEqual(set(('metadata',)), session.enabled_hook_categories)
742 -        # leaving context manager with no transaction running should reset the
743 -        # transaction local storage (and associated cnxset)
744 -        self.assertEqual({}, session._cnxs)
745 -        self.assertEqual(None, session.cnxset)
746 -        self.assertEqual(HOOKS_ALLOW_ALL, session.hooks_mode, session.HOOKS_ALLOW_ALL)
747 -        self.assertEqual(set(), session.disabled_hook_categories)
748 -        self.assertEqual(set(), session.enabled_hook_categories)
749 -
750 -    def test_explicit_connection(self):
751 -        with self.session.new_cnx() as cnx:
752 -            rset = cnx.execute('Any X LIMIT 1 WHERE X is CWUser')
753 -            self.assertEqual(1, len(rset))
754 -            user = rset.get_entity(0, 0)
755 -            user.cw_delete()
756 -            cnx.rollback()
757 -            new_user = cnx.entity_from_eid(user.eid)
758 -            self.assertIsNotNone(new_user.login)
759 -        self.assertFalse(cnx._open)
760 -
761 -    def test_internal_cnx(self):
762 -        with self.repo.internal_cnx() as cnx:
763 -            rset = cnx.execute('Any X LIMIT 1 WHERE X is CWUser')
764 -            self.assertEqual(1, len(rset))
765 -            user = rset.get_entity(0, 0)
766 -            user.cw_delete()
767 -            cnx.rollback()
768 -            new_user = cnx.entity_from_eid(user.eid)
769 -            self.assertIsNotNone(new_user.login)
770 -        self.assertFalse(cnx._open)
771 -
772 -    def test_connection_exit(self):
773 -        """exiting a connection should roll back the transaction, including any
774 -        pending operations"""
775 -        self.rollbacked = False
776 -        class RollbackOp(hook.Operation):
777 -            _test = self
778 -            def rollback_event(self):
779 -                self._test.rollbacked = True
780 -        class RollbackHook(hook.Hook):
781 -            __regid__ = 'rollback'
782 -            events = ('after_update_entity',)
783 -            __select__ = hook.Hook.__select__ & is_instance('CWGroup')
784 -            def __call__(self):
785 -                RollbackOp(self._cw)
786 -        with self.temporary_appobjects(RollbackHook):
787 -            with self.admin_access.client_cnx() as cnx:
788 -                cnx.execute('SET G name "foo" WHERE G is CWGroup, G name "managers"')
789 -            self.assertTrue(self.rollbacked)
790 -
791 -if __name__ == '__main__':
792 -    from logilab.common.testlib import unittest_main
793 -    unittest_main()