From: Jason Kirtland Date: Mon, 23 Jul 2007 20:32:19 +0000 (+0000) Subject: _ConnectionRecord gains a .properties collection, with contents scoped to X-Git-Tag: rel_0_4_6~42 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=555cb454f57ad4af5832c29d9b592588daf9e13e;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git _ConnectionRecord gains a .properties collection, with contents scoped to the lifetime of the underlying DBAPI connection. Accessors on Connections and fairies. --- diff --git a/CHANGES b/CHANGES index f6403612f0..f68b80c532 100644 --- a/CHANGES +++ b/CHANGES @@ -169,6 +169,9 @@ - better quoting of identifiers when manipulating schemas - standardized the behavior for table reflection where types can't be located; NullType is substituted instead, warning is raised. +- engines + - Connections gain a .properties collection, with contents scoped to the + lifetime of the underlying DBAPI connection - extensions - proxyengine is temporarily removed, pending an actually working replacement. diff --git a/lib/sqlalchemy/engine/base.py b/lib/sqlalchemy/engine/base.py index 5bc72db8ac..796df1a5c1 100644 --- a/lib/sqlalchemy/engine/base.py +++ b/lib/sqlalchemy/engine/base.py @@ -518,6 +518,8 @@ class Connection(Connectable): dialect = property(lambda s:s.__engine.dialect, doc="Dialect used by this Connection.") connection = property(_get_connection, doc="The underlying DBAPI connection managed by this Connection.") should_close_with_result = property(lambda s:s.__close_with_result, doc="Indicates if this Connection should be closed when a corresponding ResultProxy is closed; this is essentially an auto-release mode.") + properties = property(lambda s: s._get_connection().properties, + doc="A set of per-DBAPI connection properties.") def connect(self): """connect() is implemented to return self so that an incoming Engine or Connection object can be treated similarly.""" diff --git a/lib/sqlalchemy/pool.py b/lib/sqlalchemy/pool.py index 72325448e6..f86e14ab1e 100644 --- a/lib/sqlalchemy/pool.py +++ b/lib/sqlalchemy/pool.py @@ -190,6 +190,7 @@ class _ConnectionRecord(object): def __init__(self, pool): self.__pool = pool self.connection = self.__connect() + self.properties = {} def close(self): if self.connection is not None: @@ -207,10 +208,12 @@ class _ConnectionRecord(object): def get_connection(self): if self.connection is None: self.connection = self.__connect() + self.properties.clear() elif (self.__pool._recycle > -1 and time.time() - self.starttime > self.__pool._recycle): self.__pool.log("Connection %s exceeded timeout; recycling" % repr(self.connection)) self.__close() self.connection = self.__connect() + self.properties.clear() return self.connection def __close(self): @@ -257,6 +260,21 @@ class _ConnectionFairy(object): _logger = property(lambda self: self._pool.logger) is_valid = property(lambda self:self.connection is not None) + + def _get_properties(self): + """A property collection unique to this DBAPI connection.""" + + try: + return self._connection_record.properties + except AttributeError: + if self.connection is None: + raise exceptions.InvalidRequestError("This connection is closed") + try: + return self._detatched_properties + except AttributeError: + self._detatched_properties = value = {} + return value + properties = property(_get_properties) def invalidate(self, e=None): """Mark this connection as invalidated. @@ -301,6 +319,8 @@ class _ConnectionFairy(object): if self._connection_record is not None: self._connection_record.connection = None self._pool.do_return_conn(self._connection_record) + self._detatched_properties = \ + self._connection_record.properties.copy() self._connection_record = None def close_open_cursors(self): diff --git a/test/engine/pool.py b/test/engine/pool.py index 3bb25ec72a..364afa9d75 100644 --- a/test/engine/pool.py +++ b/test/engine/pool.py @@ -351,6 +351,35 @@ class PoolTest(PersistTest): c2 = None c1 = None self.assert_(p.checkedout() == 0) + + def test_properties(self): + dbapi = MockDBAPI() + p = pool.QueuePool(creator=lambda: dbapi.connect('foo.db'), + pool_size=1, max_overflow=0) + + c = p.connect() + self.assert_(not c.properties) + self.assert_(c.properties is c._connection_record.properties) + + c.properties['foo'] = 'bar' + c.close() + del c + + c = p.connect() + self.assert_('foo' in c.properties) + + c.invalidate() + c = p.connect() + self.assert_('foo' not in c.properties) + + c.properties['foo2'] = 'bar2' + c.detach() + self.assert_('foo2' in c.properties) + + c2 = p.connect() + self.assert_(c.connection is not c2.connection) + self.assert_(not c2.properties) + self.assert_('foo2' in c.properties) def tearDown(self): pool.clear_managers()