diff --git a/oslo_db/sqlalchemy/utils.py b/oslo_db/sqlalchemy/utils.py index 2babb184..95613d41 100644 --- a/oslo_db/sqlalchemy/utils.py +++ b/oslo_db/sqlalchemy/utils.py @@ -31,7 +31,6 @@ from sqlalchemy import Boolean from sqlalchemy import CheckConstraint from sqlalchemy import Column from sqlalchemy.engine import Connectable -from sqlalchemy.engine import reflection from sqlalchemy.engine import url as sa_url from sqlalchemy import exc from sqlalchemy import func @@ -578,12 +577,16 @@ def _change_deleted_column_type_to_boolean_sqlite(engine, table_name, column_copy = _get_not_supported_column(col_name_col_instance, column.name) else: - column_copy = column.copy() + # FIXME(stephenfin): We shouldn't be using this private API; + # figure out how else to copy an arbitrary column schema + column_copy = column._copy() else: column_copy = Column('deleted', Boolean, default=0) columns.append(column_copy) - constraints = [constraint.copy() for constraint in table.constraints] + # FIXME(stephenfin): We shouldn't be using this private API; + # figure out how else to copy an arbitrary column schema + constraints = [constraint._copy() for constraint in table.constraints] meta = table.metadata new_table = Table(table_name + "__tmp__", meta, @@ -652,15 +655,15 @@ def _is_deleted_column_constraint(constraint): def _change_deleted_column_type_to_id_type_sqlite(engine, table_name, **col_name_col_instance): - # NOTE(boris-42): sqlaclhemy-migrate can't drop column with check - # constraints in sqlite DB and our `deleted` column has - # 2 check constraints. So there is only one way to remove - # these constraints: - # 1) Create new table with the same columns, constraints - # and indexes. (except deleted column). - # 2) Copy all data from old to new table. - # 3) Drop old table. - # 4) Rename new table to old table name. + # NOTE(boris-42): sqlalchemy-migrate can't drop column with check + # constraints in sqlite DB and our `deleted` column has two check + # constraints. There is only one way to remove these constraints: + # + # 1) Create new table with the same columns, constraints and indexes. + # (except deleted column). + # 2) Copy all data from old to new table. + # 3) Drop old table. + # 4) Rename new table to old table name. meta = MetaData(bind=engine) table = Table(table_name, meta, autoload=True) default_deleted_value = _get_default_deleted_value(table) @@ -673,7 +676,9 @@ def _change_deleted_column_type_to_id_type_sqlite(engine, table_name, column_copy = _get_not_supported_column(col_name_col_instance, column.name) else: - column_copy = column.copy() + # FIXME(stephenfin): We shouldn't be using this private API; + # figure out how else to copy an arbitrary column schema + column_copy = column._copy() else: column_copy = Column('deleted', table.c.id.type, default=default_deleted_value) @@ -682,7 +687,9 @@ def _change_deleted_column_type_to_id_type_sqlite(engine, table_name, constraints = [] for constraint in table.constraints: if not _is_deleted_column_constraint(constraint): - constraints.append(constraint.copy()) + # FIXME(stephenfin): We shouldn't be using this private API; + # figure out how else to copy an arbitrary constraint schema + constraints.append(constraint._copy()) new_table = Table(table_name + "__tmp__", meta, *(columns + constraints)) @@ -734,7 +741,7 @@ def get_indexes(engine, table_name): :param table_name: name of the table """ - inspector = reflection.Inspector.from_engine(engine) + inspector = sqlalchemy.inspect(engine) indexes = inspector.get_indexes(table_name) return indexes diff --git a/oslo_db/tests/base.py b/oslo_db/tests/base.py index 8d15666a..a74ef827 100644 --- a/oslo_db/tests/base.py +++ b/oslo_db/tests/base.py @@ -12,6 +12,8 @@ from oslotest import base +from oslo_db.tests import fixtures + class BaseTestCase(base.BaseTestCase): """Test case base class for all oslo.db unit tests.""" @@ -19,3 +21,5 @@ class BaseTestCase(base.BaseTestCase): def setUp(self): """Run before each test method to initialize test environment.""" super().setUp() + + self.warning_fixture = self.useFixture(fixtures.WarningsFixture()) diff --git a/oslo_db/tests/fixtures.py b/oslo_db/tests/fixtures.py new file mode 100644 index 00000000..c08a34d9 --- /dev/null +++ b/oslo_db/tests/fixtures.py @@ -0,0 +1,36 @@ +# 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. + +import warnings + +import fixtures +from sqlalchemy import exc as sqla_exc + + +class WarningsFixture(fixtures.Fixture): + """Filters out warnings during test runs.""" + + def setUp(self): + super().setUp() + # Make deprecation warnings only happen once to avoid spamming + warnings.simplefilter('once', DeprecationWarning) + + warnings.filterwarnings( + 'error', message='Evaluating non-mapped column expression', + category=sqla_exc.SAWarning) + + # Enable deprecation warnings to capture upcoming SQLAlchemy changes + warnings.filterwarnings( + 'error', + category=sqla_exc.SADeprecationWarning) + + self.addCleanup(warnings.resetwarnings) diff --git a/oslo_db/tests/sqlalchemy/test_utils.py b/oslo_db/tests/sqlalchemy/test_utils.py index b86faf05..47d587d8 100644 --- a/oslo_db/tests/sqlalchemy/test_utils.py +++ b/oslo_db/tests/sqlalchemy/test_utils.py @@ -24,7 +24,6 @@ from sqlalchemy import CheckConstraint from sqlalchemy import MetaData, Table, Column from sqlalchemy import ForeignKey, ForeignKeyConstraint from sqlalchemy.dialects.postgresql import psycopg2 -from sqlalchemy.engine import reflection from sqlalchemy.engine import url as sa_url from sqlalchemy.exc import OperationalError from sqlalchemy.ext.declarative import declarative_base @@ -796,7 +795,7 @@ class TestMigrationUtils(db_test_base._DbTestCase): utils.change_deleted_column_type_to_id_type(self.engine, table_name) utils.change_deleted_column_type_to_boolean(self.engine, table_name) - insp = reflection.Inspector.from_engine(self.engine) + insp = sqlalchemy.inspect(self.engine) real_indexes = insp.get_indexes(table_name) self.assertEqual(3, len(real_indexes)) for index in real_indexes: