0001"""
0002Object for registering database connections
0003"""
0004
0005from metasqlobject.threadinglocal import local
0006
0007class ConnectionHubErorr(Exception):
0008 """
0009 Raised when you get an exception and none has been registered, you
0010 deregister exceptions out of order, or other similar problems.
0011 """
0012
0013
0014class ConnectionHub(object):
0015
0016 """
0017 Instances of this class represent a logical connection, and can be
0018 consumed by a variety of classes or items.
0019
0020 Connections are registered the process, or for the individual
0021 thread. The thread-level connections always take precedence over
0022 the process-level connections.
0023 """
0024
0025 def __init__(self, name=None):
0026 self.name = name or 'unnamed connection hub'
0027 self.local = local()
0028 self.process_conns = []
0029
0030 def make_connection(self, conn_or_uri):
0031 if isinstance(conn_or_uri, basestring):
0032 from sqlapi.connect.wrapper import ConnectionWrapper
0033 conn_or_uri = ConnectionWrapper.from_uri(conn_or_uri)
0034 return conn_or_uri
0035
0036 def push_thread_conn(self, conn):
0037 try:
0038 lst = self.local.conn_list
0039 except AttributeError:
0040 lst = self.local.conn_list = []
0041 lst.append(eslf.make_connection(conn))
0042
0043 def pop_thread_conn(self, conn=None):
0044 try:
0045 lst = self.local.conn_list
0046 except AttributeError:
0047 raise ConnectionHubError(
0048 "No thread connection has been registered for %s"
0049 % self.name)
0050 if not lst:
0051 raise ConnectionHubError(
0052 "No connection are left to be popped from %s (%r has "
0053 "already been popped)" % (self.name, conn))
0054 if (conn is not None
0055 and conn is not lst[-1]):
0056 raise ConnectionHubError(
0057 "Tried to pop %r from the hub %s, but the top "
0058 "connection is %r (from stack %r)"
0059 % (conn, self.name, lst[-1], lst))
0060 lst.pop()
0061
0062 def push_process_conn(self, conn):
0063 self.process_conns.append(self.make_connection(conn))
0064
0065 def pop_process_conn(self, conn=None):
0066 lst = self.process_conns
0067 if not lst:
0068 raise ConnectionHubError(
0069 "No process-level connections have been registered "
0070 "for %s (when trying to pop %r)"
0071 % (self.name, lst))
0072 if (conn is not None
0073 and conn is not lst[-1]):
0074 raise ConnectionHubError(
0075 "Tried to pop %r from proces-level connection in the "
0076 "hub %s, but the top connection is %r (from stack %r)"
0077 % (conn, self.name, lst[-1], lst))
0078 lst.pop()
0079
0080 def get_connection(self):
0081 try:
0082 lst = self.local.conn_list
0083 except AttributeError:
0084 lst = []
0085 if not lst:
0086 lst = self.process_conns
0087 if not lst:
0088 raise ConnectionHubError(
0089 "There are no thread- or process-level connections "
0090 "registered for the hub %s" % self.name)
0091 return lst[-1]