# HG changeset patch # User Pierre-Yves David # Date 1372335120 -7200 # Node ID af6efc15fc9022d6d2a74ac634b223e682eb7bb6 # Parent c859c7cef346c536f389f1d769ebb5622eab399f [repository] add an ``internal_cnx`` method to replace ``internal_session`` Accessing the repo through a Session is deprecated. We need an easy replacement for ``internal_session``. This API change was a good occasion to stop disabling integrity hook by default. This is huge source of bug in user-code. related to #2503918 diff -r c859c7cef346 -r af6efc15fc90 doc/4.0.rst --- a/doc/4.0.rst Thu Jun 27 12:02:38 2013 +0200 +++ b/doc/4.0.rst Thu Jun 27 14:12:00 2013 +0200 @@ -9,6 +9,37 @@ connection is anonymous. Beware that the ``anonymous-user`` config is web specific. Therefore, no session may be anonymous in repository only setup. +New Repository Access API +------------------------- + +Connection replace Session +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A new explicite Connection object replace Session as the main repository entry +point. Connection hold all the necessary methods to be used Server side +(``execute``, ``commit``, ``rollback``, ``call_service``, ``entity_from_eid``, +etc…). You obtains a new Connection object using ``session.new_cnx()``. +Connection object need have an explicite begin and end. Use them as a context +manager:: + + with session.new_cnx() as cnx: + self.execute('INSERT Elephant E, E name "Cabar"') + self.commit() + self.execute('INSERT Elephant E, E name "Celeste"') + self.commit() + # Once you get out of the "with" clause, the connection is closed. + +Using the same Connection object in multiple threads will give you access to the +same Transaction. However, Connection object are not thread safe. + +``repository.internal_session`` is deprecated in favor of +``repository.internal_cnx``. Note that internal connection are now safe by +default. Integrity hooks are enabled except stated otherwise. + +Backward compact is preserved on Session. They can still be used to access the +database for the next few version. + + API changes ----------- diff -r c859c7cef346 -r af6efc15fc90 server/repository.py --- a/server/repository.py Thu Jun 27 12:02:38 2013 +0200 +++ b/server/repository.py Thu Jun 27 14:12:00 2013 +0200 @@ -36,6 +36,7 @@ from os.path import join from datetime import datetime from time import time, localtime, strftime +from contextlib import contextmanager from logilab.common.decorators import cached, clear_cache from logilab.common.deprecation import deprecated @@ -945,6 +946,8 @@ nbclosed += 1 return nbclosed + @deprecated("[4.0] use internal_cnx now\n" + "(Beware that integrity hook are now enabled by default)") def internal_session(self, cnxprops=None, safe=False): """return a dbapi like connection/cursor using internal user which have every rights on the repository. The `safe` argument is a boolean flag @@ -958,6 +961,22 @@ session.set_cnxset() return session + @contextmanager + def internal_cnx(self, safe=True): + """return a Connection using internal user which have + every rights on the repository. The `safe` argument is a boolean flag + telling if integrity hooks should be activated or not. + + /!\ IN OPPOSITE OF THE OLDER INTERNAL_SESSION, INTERNAL CONNECTION ARE SAFE + /!\ BY DEFAULT. + + This is to be used a context manager. + """ + with InternalSession(self, safe) as session: + with session.new_cnx() as cnx: + yield cnx + + def _get_session(self, sessionid, setcnxset=False, txid=None, checkshuttingdown=True): """return the user associated to the given session identifier""" diff -r c859c7cef346 -r af6efc15fc90 server/session.py --- a/server/session.py Thu Jun 27 12:02:38 2013 +0200 +++ b/server/session.py Thu Jun 27 14:12:00 2013 +0200 @@ -664,7 +664,7 @@ def set_entity_cache(self, entity): """Add `entity` to the connection entity cache""" - #XXX not using _open_only because before at creation time. _set_user + # XXX not using _open_only because before at creation time. _set_user # call this function to cache the Connection user. if entity.cw_etype != 'CWUser' and not self._open: raise ProgrammingError('Closed Connection: %s' diff -r c859c7cef346 -r af6efc15fc90 server/test/unittest_session.py --- a/server/test/unittest_session.py Thu Jun 27 12:02:38 2013 +0200 +++ b/server/test/unittest_session.py Thu Jun 27 14:12:00 2013 +0200 @@ -76,6 +76,18 @@ cnx.rollback() new_user = cnx.entity_from_eid(user.eid) self.assertIsNotNone(new_user.login) + self.assertFalse(cnx._open) + + def test_internal_cnx(self): + with self.repo.internal_cnx() as cnx: + rset = cnx.execute('Any X LIMIT 1 WHERE X is CWUser') + self.assertEqual(1, len(rset)) + user = rset.get_entity(0, 0) + user.cw_delete() + cnx.rollback() + new_user = cnx.entity_from_eid(user.eid) + self.assertIsNotNone(new_user.login) + self.assertFalse(cnx._open)