From 2866272251637c0dd246c275cf04947849ea88b8 Mon Sep 17 00:00:00 2001 From: Federico Caselli Date: Mon, 8 May 2023 23:05:40 +0200 Subject: Fix compat issue with older SQLAlchemy versions. Added placeholder classes for ``Computed`` and ``Identity`` when older 1.x SQLAlchemy versions are in use, namely prior to SQLAlchemy 1.3.11 when the ``Computed`` construct was introduced. Previously these were set to None, however this could cause issues with certain codepaths that were using ``isinstance()`` such as one within "batch mode". Fixes: #1237 Change-Id: I033712158baa68cca6a56bd41d0636109e156b86 --- alembic/testing/fixtures.py | 7 ++----- alembic/testing/requirements.py | 2 +- alembic/testing/util.py | 11 +++-------- alembic/util/__init__.py | 1 - alembic/util/sqla_compat.py | 26 ++++++++++++++------------ 5 files changed, 20 insertions(+), 27 deletions(-) (limited to 'alembic') diff --git a/alembic/testing/fixtures.py b/alembic/testing/fixtures.py index ef1c3bb..65f3a0a 100644 --- a/alembic/testing/fixtures.py +++ b/alembic/testing/fixtures.py @@ -28,7 +28,7 @@ from ..operations import Operations from ..util import sqla_compat from ..util.sqla_compat import create_mock_engine from ..util.sqla_compat import sqla_14 -from ..util.sqla_compat import sqla_1x +from ..util.sqla_compat import sqla_2 testing_config = configparser.ConfigParser() @@ -36,10 +36,7 @@ testing_config.read(["test.cfg"]) class TestBase(SQLAlchemyTestBase): - if sqla_1x: - is_sqlalchemy_future = False - else: - is_sqlalchemy_future = True + is_sqlalchemy_future = sqla_2 @testing.fixture() def ops_context(self, migration_context): diff --git a/alembic/testing/requirements.py b/alembic/testing/requirements.py index a4a6045..40de4cd 100644 --- a/alembic/testing/requirements.py +++ b/alembic/testing/requirements.py @@ -84,7 +84,7 @@ class SuiteRequirements(Requirements): @property def sqlalchemy_1x(self): return exclusions.skip_if( - lambda config: not util.sqla_1x, + lambda config: util.sqla_2, "SQLAlchemy 1.x test", ) diff --git a/alembic/testing/util.py b/alembic/testing/util.py index e65597d..4517a69 100644 --- a/alembic/testing/util.py +++ b/alembic/testing/util.py @@ -6,12 +6,13 @@ # the MIT License: http://www.opensource.org/licenses/mit-license.php from __future__ import annotations -import re import types from typing import Union from sqlalchemy.util import inspect_getfullargspec +from ..util import sqla_2 + def flag_combinations(*combinations): """A facade around @testing.combinations() oriented towards boolean @@ -114,17 +115,11 @@ def _safe_int(value: str) -> Union[int, str]: def testing_engine(url=None, options=None, future=False): from sqlalchemy.testing import config from sqlalchemy.testing.engines import testing_engine - from sqlalchemy import __version__ - - _vers = tuple( - [_safe_int(x) for x in re.findall(r"(\d+|[abc]\d)", __version__)] - ) - sqla_1x = _vers < (2,) if not future: future = getattr(config._current.options, "future_engine", False) - if sqla_1x: + if not sqla_2: kw = {"future": future} if future else {} else: kw = {} diff --git a/alembic/util/__init__.py b/alembic/util/__init__.py index 8f684ab..3c1e27c 100644 --- a/alembic/util/__init__.py +++ b/alembic/util/__init__.py @@ -28,7 +28,6 @@ from .pyfiles import template_to_file from .sqla_compat import has_computed from .sqla_compat import sqla_13 from .sqla_compat import sqla_14 -from .sqla_compat import sqla_1x from .sqla_compat import sqla_2 diff --git a/alembic/util/sqla_compat.py b/alembic/util/sqla_compat.py index e2725d6..0070337 100644 --- a/alembic/util/sqla_compat.py +++ b/alembic/util/sqla_compat.py @@ -71,18 +71,17 @@ except ImportError: from sqlalchemy.sql.elements import _NONE_NAME as _NONE_NAME # type: ignore # noqa: E501 -if sqla_14: - # when future engine merges, this can be again based on version string - from sqlalchemy.engine import Connection as legacy_connection +class _Unsupported: + "Placeholder for unsupported SQLAlchemy classes" - sqla_1x = not hasattr(legacy_connection, "commit") -else: - sqla_1x = True try: - from sqlalchemy import Computed # noqa + from sqlalchemy import Computed except ImportError: - Computed = type(None) # type: ignore + + class Computed(_Unsupported): # type: ignore + pass + has_computed = False has_computed_reflection = False else: @@ -90,12 +89,15 @@ else: has_computed_reflection = _vers >= (1, 3, 16) try: - from sqlalchemy import Identity # noqa + from sqlalchemy import Identity except ImportError: - Identity = type(None) # type: ignore + + class Identity(_Unsupported): # type: ignore + pass + has_identity = False else: - # attributes common to Indentity and Sequence + # attributes common to Identity and Sequence _identity_options_attrs = ( "start", "increment", @@ -107,7 +109,7 @@ else: "cache", "order", ) - # attributes of Indentity + # attributes of Identity _identity_attrs = _identity_options_attrs + ("on_null",) has_identity = True -- cgit v1.2.1