Skip to content

Commit

Permalink
Restore compatibility with SQLAlchemy >= 1.1; < 1.4
Browse files Browse the repository at this point in the history
  • Loading branch information
adrien-berchet committed Aug 23, 2022
1 parent d6297d4 commit 0315839
Show file tree
Hide file tree
Showing 9 changed files with 64 additions and 24 deletions.
4 changes: 4 additions & 0 deletions doc/alembic.rst
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ In this case, we have to do the following changes to make it work:
Helpers
-------

.. warning::

The helpers described in this section need `SQLAlchemy>=1.4`.

In order to make the use of Alembic easier, a few helpers are provided in
:ref:`geoalchemy2.alembic_helpers <alembic_helpers>`. These helpers can be used in the ``env.py``
file used by Alembic to auto-generate the migration scripts, like in the following example:
Expand Down
13 changes: 8 additions & 5 deletions geoalchemy2/alembic_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,14 @@ def spatial_behavior(self, connection, table_name, schema=None, **kw):
connection, table_name, schema=None, **kw
)

# Check that SpatiaLite was loaded into the DB
is_spatial_db = connection.exec_driver_sql(
"""PRAGMA main.table_info(geometry_columns)"""
).fetchall()
if not is_spatial_db:
try:
# Check that SpatiaLite was loaded into the DB
is_spatial_db = connection.exec_driver_sql(
"""PRAGMA main.table_info(geometry_columns)"""
).fetchall()
if not is_spatial_db:
return indexes
except AttributeError:
return indexes

# Get spatial indexes
Expand Down
17 changes: 9 additions & 8 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@
universal = 1

[tox:tox]
envlist = py{37,38,39,310}-sqla{14, latest}, pypy3-sqla{14, latest}, lint, coverage, docs
envlist = py{37,38,39,310}-sqla{11, latest}, pypy3-sqla{11, latest}, lint, coverage, docs
requires=
setuptools>42

[gh-actions]
python =
3.7: py37-sqla{14, latest}, lint
3.8: py38-sqla{14, latest}, docs
3.9: py39-sqla{14, latest}
3.10: py310-sqla{14, latest}
pypy-3.8: pypy3-sqla{14, latest}
3.7: py37-sqla{11, latest}, lint
3.8: py38-sqla{11, latest}, docs
3.9: py39-sqla{11, latest}
3.10: py310-sqlalatest
pypy-3.8: pypy3-sqla{11, latest}

[testenv]
passenv=
Expand All @@ -22,11 +22,12 @@ passenv=
SPATIALITE_DB_PATH
setenv=
COVERAGE_FILE = {env:COVERAGE_FILE:.coverage-{envname}}
EXPECTED_COV = 91
sqla11: EXPECTED_COV = 75
sqlalatest: EXPECTED_COV = 91
pypy3: EXPECTED_COV = 77
deps=
alembic
sqla14: SQLAlchemy==1.4.*
sqla11: SQLAlchemy==1.1.2
sqlalatest: SQLAlchemy
!pypy3: psycopg2
pypy3: psycopg2cffi
Expand Down
3 changes: 2 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,10 @@
zip_safe=False,
setup_requires=["setuptools_scm"],
install_requires=[
'SQLAlchemy>=1.4',
'SQLAlchemy>=1.1',
'packaging'
],
extras_require={"alembic": ["alembic", "sqlalchemy>=1.4"]},
entry_points="""
# -*- Entry points: -*-
""",
Expand Down
5 changes: 5 additions & 0 deletions tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,11 @@ def skip_pg12_sa1217(bind):
pytest.skip("Reflection for PostgreSQL-12 is only supported by sqlalchemy>=1.2.17")


def skip_sa11():
if parse_version(SA_VERSION) < parse_version("1.4"):
pytest.skip("Requires SQLAlchely>=1.4")


def select(args):
if version.parse(SA_VERSION) < version.parse("1.4"):
return raw_select(args)
Expand Down
20 changes: 20 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@
from sqlalchemy import MetaData
from sqlalchemy import create_engine
from sqlalchemy import text
from sqlalchemy.dialects.sqlite.base import SQLiteDialect
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

from geoalchemy2.alembic_helpers import _monkey_patch_get_indexes_for_sqlite

from . import copy_and_connect_sqlite_db
from . import get_postgis_version
from . import get_postgres_major_version
Expand Down Expand Up @@ -179,6 +182,23 @@ def postgres_major_version(conn):
return get_postgres_major_version(conn)


@pytest.fixture(autouse=True)
def reset_sqlite_monkeypatch():
"""Disable Alembic monkeypatching by default."""
try:
normal_behavior = SQLiteDialect._get_indexes_normal_behavior
SQLiteDialect.get_indexes = normal_behavior
SQLiteDialect._get_indexes_normal_behavior = normal_behavior
except AttributeError:
pass


@pytest.fixture(autouse=True)
def use_sqlite_monkeypatch():
"""Enable Alembic monkeypatching ."""
_monkey_patch_get_indexes_for_sqlite()


@pytest.fixture
def setup_tables(session, metadata):
conn = session.connection()
Expand Down
9 changes: 2 additions & 7 deletions tests/gallery/test_summarystatsagg.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,10 @@
Some functions return composite types. This example shows how to deal with this
kind of functions.
"""
import pytest
from pkg_resources import parse_version
from sqlalchemy import Column
from sqlalchemy import Float
from sqlalchemy import Integer
from sqlalchemy import MetaData
from sqlalchemy import __version__ as SA_VERSION
from sqlalchemy.ext.declarative import declarative_base

from geoalchemy2 import Raster
Expand All @@ -21,6 +18,7 @@

# Tests imports
from tests import select
from tests import skip_sa11
from tests import test_only_with_dialects


Expand Down Expand Up @@ -62,11 +60,8 @@ def __init__(self, rast):
@test_only_with_dialects("postgresql")
class TestSTSummaryStatsAgg():

@pytest.mark.skipif(
parse_version(SA_VERSION) < parse_version("1.4"),
reason="requires SQLAlchely>1.4",
)
def test_st_summary_stats_agg(self, session, conn):
skip_sa11()
metadata.drop_all(conn, checkfirst=True)
metadata.create_all(conn)

Expand Down
10 changes: 7 additions & 3 deletions tests/test_alembic_migrations.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from geoalchemy2 import alembic_helpers

from . import check_indexes
from . import skip_sa11
from . import test_only_with_dialects


Expand All @@ -26,8 +27,9 @@ def filter_tables(name, type_, parent_names):


class TestAutogenerate:
def test_no_diff(self, conn, Lake, setup_tables):
def test_no_diff(self, conn, Lake, setup_tables, use_sqlite_monkeypatch):
"""Check that the autogeneration detects spatial types properly."""
skip_sa11()
metadata = MetaData()

Table(
Expand Down Expand Up @@ -57,8 +59,9 @@ def test_no_diff(self, conn, Lake, setup_tables):

assert diff == []

def test_diff(self, conn, Lake, setup_tables):
def test_diff(self, conn, Lake, setup_tables, use_sqlite_monkeypatch):
"""Check that the autogeneration detects spatial types properly."""
skip_sa11()
metadata = MetaData()

Table(
Expand Down Expand Up @@ -255,8 +258,9 @@ class = StreamHandler

@test_only_with_dialects("postgresql", "sqlite-spatialite4")
def test_migration_revision(
conn, metadata, alembic_config, alembic_env_path, test_script_path
conn, metadata, alembic_config, alembic_env_path, test_script_path, use_sqlite_monkeypatch
):
skip_sa11()
if platform.python_implementation().lower() == 'pypy':
pytest.skip('skip SpatiaLite tests on PyPy', allow_module_level=True)

Expand Down
7 changes: 7 additions & 0 deletions tests/test_functional.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
from . import skip_case_insensitivity
from . import skip_pg12_sa1217
from . import skip_postgis1
from . import skip_sa11
from . import test_only_with_dialects

SQLA_LT_2 = parse_version(SA_VERSION) <= parse_version("1.999")
Expand Down Expand Up @@ -77,6 +78,7 @@ class TestMiscellaneous():

@test_only_with_dialects("sqlite")
def test_load_spatialite(self, monkeypatch, conn):
skip_sa11()
geoalchemy2.load_spatialite(conn.connection.dbapi_connection, None)

monkeypatch.delenv("SPATIALITE_LIBRARY_PATH")
Expand Down Expand Up @@ -646,6 +648,7 @@ def setup_reflection_tables(self, reflection_tables_metadata, conn):

def test_reflection(self, conn, setup_reflection_tables):
skip_pg12_sa1217(conn)
skip_sa11()
t = Table(
'lake',
MetaData(),
Expand Down Expand Up @@ -774,6 +777,7 @@ def test_reflection(self, conn, setup_reflection_tables):
def test_raster_reflection(self, conn, Ocean, setup_tables):
skip_pg12_sa1217(conn)
skip_postgis1(conn)
skip_sa11()
with pytest.warns(SAWarning):
t = Table('ocean', MetaData(), autoload_with=conn)
type_ = t.c.rast.type
Expand All @@ -782,6 +786,7 @@ def test_raster_reflection(self, conn, Ocean, setup_tables):
@test_only_with_dialects("sqlite")
def test_sqlite_reflection_with_discarded_col(self, conn, Lake, setup_tables):
"""Test that a discarded geometry column is not properly reflected with SQLite."""
skip_sa11()
conn.execute("""DELETE FROM "geometry_columns" WHERE f_table_name = 'lake';""")
t = Table(
'lake',
Expand Down Expand Up @@ -812,6 +817,7 @@ def test_view_reflection(self, conn, Ocean, setup_tables, ocean_view):
"""
skip_pg12_sa1217(conn)
skip_postgis1(conn)
skip_sa11()
t = Table('test_view', MetaData(), autoload_with=conn)
type_ = t.c.rast.type
assert isinstance(type_, Raster)
Expand All @@ -820,6 +826,7 @@ def test_view_reflection(self, conn, Ocean, setup_tables, ocean_view):
class TestToMetadata(ComparesTables):

def test_to_metadata(self, Lake):
skip_sa11()
new_meta = MetaData()
new_Lake = Lake.__table__.to_metadata(new_meta)

Expand Down

0 comments on commit 0315839

Please sign in to comment.