[doc/book] mention that the shell is a python shell
# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr## This file is part of CubicWeb.## CubicWeb is free software: you can redistribute it and/or modify it under the# terms of the GNU Lesser General Public License as published by the Free# Software Foundation, either version 2.1 of the License, or (at your option)# any later version.## CubicWeb is distributed in the hope that it will be useful, but WITHOUT# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more# details.## You should have received a copy of the GNU Lesser General Public License along# with CubicWeb. If not, see <http://www.gnu.org/licenses/>."""CubicWeb server connections pool : the repository has a limited number ofconnections pools, each of them dealing with a set of connections on each sourceused by the repository. A connections pools (`ConnectionsPool`) is anabstraction for a group of connection to each source."""__docformat__="restructuredtext en"importsysclassConnectionsPool(object):"""handle connections on a set of sources, at some point associated to a user session """def__init__(self,sources):# dictionnary of (source, connection), indexed by sources'uriself.source_cnxs={}forsourceinsources:self.add_source(source)ifnot'system'inself.source_cnxs:self.source_cnxs['system']=self.source_cnxs[sources[0].uri]self._cursors={}def__getitem__(self,uri):"""subscription notation provide access to sources'cursors"""try:cursor=self._cursors[uri]exceptKeyError:cursor=self.source_cnxs[uri][1].cursor()ifcursorisnotNone:# None possible on sources without cursor support such as ldapself._cursors[uri]=cursorreturncursordefadd_source(self,source):assertnotsource.uriinself.source_cnxsself.source_cnxs[source.uri]=(source,source.get_connection())defremove_source(self,source):source,cnx=self.source_cnxs.pop(source.uri)cnx.close()self._cursors.pop(source.uri,None)defcommit(self):"""commit the current transaction for this user"""# FIXME: what happends if a commit fail# would need a two phases commit or like, but I don't know how to do# this using the db-api...forsource,cnxinself.source_cnxs.values():# let exception propagatescnx.commit()defrollback(self):"""rollback the current transaction for this user"""forsource,cnxinself.source_cnxs.values():# catch exceptions, rollback other sources anywaytry:cnx.rollback()except:source.critical('rollback error',exc_info=sys.exc_info())# error on rollback, the connection is much probably in a really# bad state. Replace it by a new one.self.reconnect(source)defclose(self,i_know_what_i_do=False):"""close all connections in the pool"""ifi_know_what_i_doisnotTrue:# unexpected closing safety beltraiseRuntimeError('pool shouldn\'t be closed')forcuinself._cursors.values():try:cu.close()except:continuefor_,cnxinself.source_cnxs.values():try:cnx.close()except:continue# internals ###############################################################defpool_set(self):"""pool is being set"""self.check_connections()defpool_reset(self):"""pool is being reseted"""forsource,cnxinself.source_cnxs.values():source.pool_reset(cnx)defsources(self):"""return the source objects handled by this pool"""# implementation details of flying insert requires the system source# firstyieldself.source_cnxs['system'][0]foruri,(source,cnx)inself.source_cnxs.items():ifuri=='system':continueyieldsource#return [source_cnx[0] for source_cnx in self.source_cnxs.values()]defsource(self,uid):"""return the source object with the given uri"""returnself.source_cnxs[uid][0]defconnection(self,uid):"""return the connection on the source object with the given uri"""returnself.source_cnxs[uid][1]defreconnect(self,source=None):"""reopen a connection for this source or all sources if none specified """ifsourceisNone:sources=self.sources()else:sources=(source,)forsourceinsources:try:# properly close existing connection if anyself.source_cnxs[source.uri][1].close()except:passsource.info('trying to reconnect')self.source_cnxs[source.uri]=(source,source.get_connection())self._cursors.pop(source.uri,None)defcheck_connections(self):forsource,cnxinself.source_cnxs.itervalues():newcnx=source.check_connection(cnx)ifnewcnxisnotNone:self.reset_connection(source,newcnx)defreset_connection(self,source,cnx):self.source_cnxs[source.uri]=(source,cnx)self._cursors.pop(source.uri,None)fromcubicweb.server.hookimportOperation,LateOperation,SingleLastOperationfromlogilab.common.deprecationimportclass_moved,class_renamedOperation=class_moved(Operation)PreCommitOperation=class_renamed('PreCommitOperation',Operation)LateOperation=class_moved(LateOperation)SingleLastOperation=class_moved(SingleLastOperation)