summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2015-04-14 13:53:04 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2015-04-28 10:56:05 -0400
commit4d3a7a662e2049cc7b2bf9b85abb1178d3849139 (patch)
tree0a4c2576d564bdd679fe7f3061047929f8e06282
parent04eba07c675435ea9290f6365c41103a291359a3 (diff)
downloadoslo-db-4d3a7a662e2049cc7b2bf9b85abb1178d3849139.tar.gz
Remove pre-SQLAlchemy-0.9.7 compat utilities
Now that requirements.txt is at SQLAlchemy 0.9.7 at the minimum, we can remove the engine_connect compatibility module as well as part of the handle_error compatibility module. In particular, this gives us the ability to add and remove engine_connect events using the event API directly which can be handy in test fixtures. Change-Id: I48450ad9d472d4377913ad391a0f5e3ba0f1471f
-rw-r--r--oslo/db/sqlalchemy/compat/__init__.py1
-rw-r--r--oslo_db/sqlalchemy/compat/__init__.py5
-rw-r--r--oslo_db/sqlalchemy/compat/engine_connect.py60
-rw-r--r--oslo_db/sqlalchemy/compat/handle_error.py126
-rw-r--r--oslo_db/sqlalchemy/session.py4
-rw-r--r--oslo_db/tests/old_import_api/sqlalchemy/test_engine_connect.py68
-rw-r--r--oslo_db/tests/old_import_api/sqlalchemy/test_exc_filters.py5
-rw-r--r--oslo_db/tests/sqlalchemy/test_engine_connect.py68
-rw-r--r--oslo_db/tests/sqlalchemy/test_exc_filters.py7
9 files changed, 21 insertions, 323 deletions
diff --git a/oslo/db/sqlalchemy/compat/__init__.py b/oslo/db/sqlalchemy/compat/__init__.py
index 86436ec..4cd5ba6 100644
--- a/oslo/db/sqlalchemy/compat/__init__.py
+++ b/oslo/db/sqlalchemy/compat/__init__.py
@@ -12,6 +12,5 @@
# License for the specific language governing permissions and limitations
# under the License.
-from oslo_db.sqlalchemy.compat import engine_connect # noqa
from oslo_db.sqlalchemy.compat import handle_error # noqa
from oslo_db.sqlalchemy.compat import utils # noqa
diff --git a/oslo_db/sqlalchemy/compat/__init__.py b/oslo_db/sqlalchemy/compat/__init__.py
index 3dc29ac..0a054d8 100644
--- a/oslo_db/sqlalchemy/compat/__init__.py
+++ b/oslo_db/sqlalchemy/compat/__init__.py
@@ -16,13 +16,10 @@ added at some point but for which oslo.db provides a compatible versions
for previous SQLAlchemy versions.
"""
-from oslo_db.sqlalchemy.compat import engine_connect as _e_conn
from oslo_db.sqlalchemy.compat import handle_error as _h_err
# trying to get: "from oslo_db.sqlalchemy import compat; compat.handle_error"
# flake8 won't let me import handle_error directly
-engine_connect = _e_conn.engine_connect
handle_error = _h_err.handle_error
-__all__ = [
- 'engine_connect', 'handle_error']
+__all__ = ['handle_error']
diff --git a/oslo_db/sqlalchemy/compat/engine_connect.py b/oslo_db/sqlalchemy/compat/engine_connect.py
deleted file mode 100644
index 6b50fc6..0000000
--- a/oslo_db/sqlalchemy/compat/engine_connect.py
+++ /dev/null
@@ -1,60 +0,0 @@
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-"""Provide forwards compatibility for the engine_connect event.
-
-See the "engine_connect" event at
-http://docs.sqlalchemy.org/en/rel_0_9/core/events.html.
-
-
-"""
-
-from sqlalchemy.engine import Engine
-from sqlalchemy import event
-
-from oslo_db.sqlalchemy.compat import utils
-
-
-def engine_connect(engine, listener):
- """Add an engine_connect listener for the given :class:`.Engine`.
-
- This listener uses the SQLAlchemy
- :meth:`sqlalchemy.event.ConnectionEvents.engine_connect`
- event for 0.9.0 and above, and implements an interim listener
- for 0.8 versions.
-
- """
- if utils.sqla_090:
- event.listen(engine, "engine_connect", listener)
- return
-
- assert isinstance(engine, Engine), \
- "engine argument must be an Engine instance, not a Connection"
-
- if not getattr(engine._connection_cls,
- '_oslo_engine_connect_wrapper', False):
- engine._oslo_engine_connect_events = []
-
- class Connection(engine._connection_cls):
- _oslo_engine_connect_wrapper = True
-
- def __init__(self, *arg, **kw):
- super(Connection, self).__init__(*arg, **kw)
-
- _oslo_engine_connect_events = getattr(
- self.engine,
- '_oslo_engine_connect_events',
- False)
- if _oslo_engine_connect_events:
- for fn in _oslo_engine_connect_events:
- fn(self, kw.get('_branch', False))
- engine._connection_cls = Connection
- engine._oslo_engine_connect_events.append(listener)
diff --git a/oslo_db/sqlalchemy/compat/handle_error.py b/oslo_db/sqlalchemy/compat/handle_error.py
index 5169857..a7efcdc 100644
--- a/oslo_db/sqlalchemy/compat/handle_error.py
+++ b/oslo_db/sqlalchemy/compat/handle_error.py
@@ -32,8 +32,7 @@ def handle_error(engine, listener):
This listener uses the SQLAlchemy
:meth:`sqlalchemy.event.ConnectionEvents.handle_error`
- event, however augments the listener for pre-0.9.7 versions of SQLAlchemy
- in order to support safe re-raise of the exception.
+ event.
"""
if utils.sqla_100:
@@ -43,122 +42,17 @@ def handle_error(engine, listener):
assert isinstance(engine, Engine), \
"engine argument must be an Engine instance, not a Connection"
- if not utils.sqla_097:
- _rework_handle_exception_for_events(engine)
- engine._oslo_handle_error_events.append(listener)
+ assert utils.sqla_097
_rework_connect_and_revalidate_for_events(engine)
- if utils.sqla_097:
- # ctx.engine added per
- # https://bitbucket.org/zzzeek/sqlalchemy/issue/3266/
- def wrap_listener(ctx):
- if isinstance(ctx, engine_base.ExceptionContextImpl):
- ctx.engine = ctx.connection.engine
- return listener(ctx)
- event.listen(engine, "handle_error", wrap_listener)
-
-
-def _rework_handle_exception_for_events(engine):
- """Patch the _handle_dbapi_error() system on Connection.
-
- This allows the 0.9.7-style handle_error() event to be available on
- the Connection object.
-
- """
- engine._oslo_handle_error_events = []
-
- class Connection(engine._connection_cls):
- def _handle_dbapi_exception(self, e, statement, parameters,
- cursor, context):
-
- try:
- super(Connection, self)._handle_dbapi_exception(
- e, statement, parameters, cursor, context)
- except Exception as reraised_exception:
- # all versions:
- # _handle_dbapi_exception reraises all DBAPI errors
- # 0.8 and above:
- # reraises all errors unconditionally
- pass
- else:
- # 0.7.8:
- # _handle_dbapi_exception does not unconditionally
- # re-raise
- reraised_exception = e
-
- _oslo_handle_error_events = getattr(
- self.engine,
- '_oslo_handle_error_events',
- False)
-
- newraise = None
- if _oslo_handle_error_events:
- if isinstance(reraised_exception,
- sqla_exc.StatementError):
- sqlalchemy_exception = reraised_exception
- original_exception = sqlalchemy_exception.orig
- self._is_disconnect = is_disconnect = (
- isinstance(sqlalchemy_exception,
- sqla_exc.DBAPIError)
- and sqlalchemy_exception.connection_invalidated)
- else:
- sqlalchemy_exception = None
- original_exception = reraised_exception
- is_disconnect = False
-
- # new handle_error event
- ctx = ExceptionContextImpl(
- original_exception, sqlalchemy_exception,
- self.engine, self, cursor, statement,
- parameters, context, is_disconnect)
-
- for fn in _oslo_handle_error_events:
- try:
- # handler returns an exception;
- # call next handler in a chain
- per_fn = fn(ctx)
- if per_fn is not None:
- ctx.chained_exception = newraise = per_fn
- except Exception as _raised:
- # handler raises an exception - stop processing
- newraise = _raised
- break
-
- if sqlalchemy_exception and \
- self._is_disconnect != ctx.is_disconnect:
-
- if not ctx.is_disconnect:
- raise NotImplementedError(
- "Can't reset 'disconnect' status of exception "
- "once it is set with this version of "
- "SQLAlchemy")
-
- sqlalchemy_exception.connection_invalidated = \
- self._is_disconnect = ctx.is_disconnect
- if self._is_disconnect:
- self._do_disconnect(e)
-
- if newraise:
- six.reraise(type(newraise), newraise, sys.exc_info()[2])
- else:
- six.reraise(type(reraised_exception),
- reraised_exception, sys.exc_info()[2])
-
- def _do_disconnect(self, e):
- del self._is_disconnect
- if utils.sqla_094:
- dbapi_conn_wrapper = self.connection
- self.engine.pool._invalidate(dbapi_conn_wrapper, e)
- self.invalidate(e)
- else:
- dbapi_conn_wrapper = self.connection
- self.invalidate(e)
- if not hasattr(dbapi_conn_wrapper, '_pool') or \
- dbapi_conn_wrapper._pool is self.engine.pool:
- self.engine.dispose()
-
- engine._connection_cls = Connection
+ # ctx.engine added per
+ # https://bitbucket.org/zzzeek/sqlalchemy/issue/3266/
+ def wrap_listener(ctx):
+ if isinstance(ctx, engine_base.ExceptionContextImpl):
+ ctx.engine = ctx.connection.engine
+ return listener(ctx)
+ event.listen(engine, "handle_error", wrap_listener)
def _rework_connect_and_revalidate_for_events(engine):
@@ -335,6 +229,8 @@ class ExceptionContextImpl(object):
This is for forwards compatibility with the
ExceptionContext interface introduced in SQLAlchemy 0.9.7.
+ It also provides for the "engine" argument added in SQLAlchemy 1.0.0.
+
"""
def __init__(self, exception, sqlalchemy_exception,
diff --git a/oslo_db/sqlalchemy/session.py b/oslo_db/sqlalchemy/session.py
index ce347ce..f243652 100644
--- a/oslo_db/sqlalchemy/session.py
+++ b/oslo_db/sqlalchemy/session.py
@@ -286,6 +286,7 @@ import time
from oslo_utils import timeutils
import six
+from sqlalchemy import event
from sqlalchemy import exc
import sqlalchemy.orm
from sqlalchemy import pool
@@ -295,7 +296,6 @@ from sqlalchemy.sql.expression import select
from oslo_db._i18n import _LW
from oslo_db import exception
from oslo_db import options
-from oslo_db.sqlalchemy import compat
from oslo_db.sqlalchemy import exc_filters
from oslo_db.sqlalchemy import update_match
from oslo_db.sqlalchemy import utils
@@ -408,7 +408,7 @@ def create_engine(sql_connection, sqlite_fk=False, mysql_sql_mode=None,
exc_filters.register_engine(engine)
# register engine connect handler
- compat.engine_connect(engine, _connect_ping_listener)
+ event.listen(engine, "engine_connect", _connect_ping_listener)
# initial connect + test
_test_connection(engine, max_retries, retry_interval)
diff --git a/oslo_db/tests/old_import_api/sqlalchemy/test_engine_connect.py b/oslo_db/tests/old_import_api/sqlalchemy/test_engine_connect.py
deleted file mode 100644
index 54e359f..0000000
--- a/oslo_db/tests/old_import_api/sqlalchemy/test_engine_connect.py
+++ /dev/null
@@ -1,68 +0,0 @@
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-"""Test the compatibility layer for the engine_connect() event.
-
-This event is added as of SQLAlchemy 0.9.0; oslo.db provides a compatibility
-layer for prior SQLAlchemy versions.
-
-"""
-
-import mock
-from oslotest import base as test_base
-import sqlalchemy as sqla
-
-from oslo.db.sqlalchemy import compat
-
-
-class EngineConnectTest(test_base.BaseTestCase):
-
- def setUp(self):
- super(EngineConnectTest, self).setUp()
-
- self.engine = engine = sqla.create_engine("sqlite://")
- self.addCleanup(engine.dispose)
-
- def test_connect_event(self):
- engine = self.engine
-
- listener = mock.Mock()
- compat.engine_connect(engine, listener)
-
- conn = engine.connect()
- self.assertEqual(
- listener.mock_calls,
- [mock.call(conn, False)]
- )
-
- conn.close()
-
- conn2 = engine.connect()
- conn2.close()
- self.assertEqual(
- listener.mock_calls,
- [mock.call(conn, False), mock.call(conn2, False)]
- )
-
- def test_branch(self):
- engine = self.engine
-
- listener = mock.Mock()
- compat.engine_connect(engine, listener)
-
- conn = engine.connect()
- branched = conn.connect()
- conn.close()
- self.assertEqual(
- listener.mock_calls,
- [mock.call(conn, False), mock.call(branched, True)]
- )
diff --git a/oslo_db/tests/old_import_api/sqlalchemy/test_exc_filters.py b/oslo_db/tests/old_import_api/sqlalchemy/test_exc_filters.py
index 77670be..0b1bb89 100644
--- a/oslo_db/tests/old_import_api/sqlalchemy/test_exc_filters.py
+++ b/oslo_db/tests/old_import_api/sqlalchemy/test_exc_filters.py
@@ -19,10 +19,10 @@ import mock
from oslotest import base as oslo_test_base
import six
import sqlalchemy as sqla
+from sqlalchemy import event
from sqlalchemy.orm import mapper
from oslo.db import exception
-from oslo.db.sqlalchemy import compat
from oslo.db.sqlalchemy import exc_filters
from oslo.db.sqlalchemy import test_base
from oslo_db.sqlalchemy import session as private_session
@@ -719,7 +719,8 @@ class TestDBDisconnected(TestsExceptionFilter):
dialect_name, exception, num_disconnects, is_disconnect=True):
engine = self.engine
- compat.engine_connect(engine, private_session._connect_ping_listener)
+ event.listen(
+ engine, "engine_connect", private_session._connect_ping_listener)
real_do_execute = engine.dialect.do_execute
counter = itertools.count(1)
diff --git a/oslo_db/tests/sqlalchemy/test_engine_connect.py b/oslo_db/tests/sqlalchemy/test_engine_connect.py
deleted file mode 100644
index c75511f..0000000
--- a/oslo_db/tests/sqlalchemy/test_engine_connect.py
+++ /dev/null
@@ -1,68 +0,0 @@
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-"""Test the compatibility layer for the engine_connect() event.
-
-This event is added as of SQLAlchemy 0.9.0; oslo_db provides a compatibility
-layer for prior SQLAlchemy versions.
-
-"""
-
-import mock
-from oslotest import base as test_base
-import sqlalchemy as sqla
-
-from oslo_db.sqlalchemy.compat import engine_connect
-
-
-class EngineConnectTest(test_base.BaseTestCase):
-
- def setUp(self):
- super(EngineConnectTest, self).setUp()
-
- self.engine = engine = sqla.create_engine("sqlite://")
- self.addCleanup(engine.dispose)
-
- def test_connect_event(self):
- engine = self.engine
-
- listener = mock.Mock()
- engine_connect(engine, listener)
-
- conn = engine.connect()
- self.assertEqual(
- listener.mock_calls,
- [mock.call(conn, False)]
- )
-
- conn.close()
-
- conn2 = engine.connect()
- conn2.close()
- self.assertEqual(
- listener.mock_calls,
- [mock.call(conn, False), mock.call(conn2, False)]
- )
-
- def test_branch(self):
- engine = self.engine
-
- listener = mock.Mock()
- engine_connect(engine, listener)
-
- conn = engine.connect()
- branched = conn.connect()
- conn.close()
- self.assertEqual(
- listener.mock_calls,
- [mock.call(conn, False), mock.call(branched, True)]
- )
diff --git a/oslo_db/tests/sqlalchemy/test_exc_filters.py b/oslo_db/tests/sqlalchemy/test_exc_filters.py
index dc5de84..bafb59e 100644
--- a/oslo_db/tests/sqlalchemy/test_exc_filters.py
+++ b/oslo_db/tests/sqlalchemy/test_exc_filters.py
@@ -19,10 +19,10 @@ import mock
from oslotest import base as oslo_test_base
import six
import sqlalchemy as sqla
+from sqlalchemy import event
from sqlalchemy.orm import mapper
from oslo_db import exception
-from oslo_db.sqlalchemy import compat
from oslo_db.sqlalchemy import exc_filters
from oslo_db.sqlalchemy import session
from oslo_db.sqlalchemy import test_base
@@ -784,7 +784,7 @@ class TestDBDisconnected(TestsExceptionFilter):
dialect_name, exception, num_disconnects, is_disconnect=True):
engine = self.engine
- compat.engine_connect(engine, session._connect_ping_listener)
+ event.listen(engine, "engine_connect", session._connect_ping_listener)
real_do_execute = engine.dialect.do_execute
counter = itertools.count(1)
@@ -966,7 +966,8 @@ class TestDBConnectPingWrapping(TestsExceptionFilter):
def setUp(self):
super(TestDBConnectPingWrapping, self).setUp()
- compat.engine_connect(self.engine, session._connect_ping_listener)
+ event.listen(
+ self.engine, "engine_connect", session._connect_ping_listener)
@contextlib.contextmanager
def _fixture(