Skip to content

Commit 1ba220b

Browse files
committed
Drop sqlalchemy 1.4 support
sqlalchemy 1.4 is EOL. https://www.sqlalchemy.org/download.html#relstatus
1 parent 60555f2 commit 1ba220b

11 files changed

Lines changed: 20 additions & 79 deletions

File tree

.github/workflows/test.yaml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ jobs:
1212
- '3.12'
1313
- '3.13'
1414
- '3.14'
15-
tox_env: ['sqlalchemy14', 'sqlalchemy2']
1615
runs-on: ${{ matrix.os }}
1716
services:
1817
postgres:
@@ -68,7 +67,7 @@ jobs:
6867
- name: Run tests
6968
env:
7069
SQLALCHEMY_UTILS_TEST_POSTGRESQL_PASSWORD: postgres
71-
run: tox -e ${{ matrix.tox_env }}
70+
run: tox -e py${{ matrix.python-version }}
7271

7372
docs:
7473
runs-on: 'ubuntu-latest'

CHANGES.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ Here you can see the full list of changes between each SQLAlchemy-Utils release.
66
Unreleased
77
^^^^^^^^^^
88

9+
- Drop support for sqlalchemy 1.4.
910
- Drop support for Python 3.9.
1011
- Support Python 3.14.
1112
- Fix ``ChoiceType`` returning the raw scalar instead of a ``Choice`` for falsy codes such as ``0`` or the empty string. (#813)

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ classifiers = [
2929
"Topic :: Software Development :: Libraries :: Python Modules",
3030
]
3131
dependencies = [
32-
"SQLAlchemy>=1.4",
32+
"SQLAlchemy>=2.0",
3333
]
3434

3535
[project.urls]

sqlalchemy_utils/functions/database.py

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import itertools
22
import os
33
from collections.abc import Mapping, Sequence
4-
from copy import copy
54

65
import sqlalchemy as sa
76
from sqlalchemy.engine.url import make_url
@@ -416,13 +415,8 @@ def _set_url_database(url: sa.engine.url.URL, database):
416415
:param database: New database to set.
417416
418417
"""
419-
if hasattr(url, '_replace'):
420-
# Cannot use URL.set() as database may need to be set to None.
421-
ret = url._replace(database=database)
422-
else: # SQLAlchemy <1.4
423-
url = copy(url)
424-
url.database = database
425-
ret = url
418+
# Cannot use URL.set() as database may need to be set to None.
419+
ret = url._replace(database=database)
426420
assert ret.database == database, ret
427421
return ret
428422

sqlalchemy_utils/functions/mock.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,7 @@ def render_literal_value(self, value, type_):
4747
def dump(*args, **kw):
4848
return None
4949

50-
try:
51-
engine = sa.create_mock_engine(bind_url, executor=dump)
52-
except AttributeError: # SQLAlchemy <1.4
53-
engine = sa.create_engine(bind_url, strategy='mock', executor=dump)
50+
engine = sa.create_mock_engine(bind_url, executor=dump)
5451
return engine
5552

5653

sqlalchemy_utils/functions/orm.py

Lines changed: 9 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,7 @@
1010
from sqlalchemy.orm.attributes import InstrumentedAttribute
1111
from sqlalchemy.orm.exc import UnmappedInstanceError
1212

13-
try:
14-
from sqlalchemy.orm.context import _ColumnEntity, _MapperEntity
15-
except ImportError: # SQLAlchemy <1.4
16-
from sqlalchemy.orm.query import _ColumnEntity, _MapperEntity
13+
from sqlalchemy.orm.context import _ColumnEntity, _MapperEntity
1714

1815
from sqlalchemy.orm.session import object_session
1916
from sqlalchemy.orm.util import AliasedInsp
@@ -281,12 +278,9 @@ def get_mapper(mixed):
281278
if isinstance(mixed, sa.orm.attributes.InstrumentedAttribute):
282279
mixed = mixed.class_
283280
if isinstance(mixed, sa.Table):
284-
if hasattr(mapperlib, '_all_registries'):
285-
all_mappers = set()
286-
for mapper_registry in mapperlib._all_registries():
287-
all_mappers.update(mapper_registry.mappers)
288-
else: # SQLAlchemy <1.4
289-
all_mappers = mapperlib._mapper_registry
281+
all_mappers = set()
282+
for mapper_registry in mapperlib._all_registries():
283+
all_mappers.update(mapper_registry.mappers)
290284
mappers = [mapper for mapper in all_mappers if mixed in mapper.tables]
291285
if len(mappers) > 1:
292286
raise ValueError("Multiple mappers found for table '%s'." % mixed.name)
@@ -449,11 +443,10 @@ def get_columns(mixed):
449443
SA Table object, SA Mapper, SA declarative class, SA declarative class
450444
instance or an alias of any of these objects
451445
"""
446+
if isinstance(mixed, sa.SelectBase):
447+
return mixed.subquery().c
452448
if isinstance(mixed, sa.sql.selectable.Selectable):
453-
try:
454-
return mixed.selected_columns
455-
except AttributeError: # SQLAlchemy <1.4
456-
return mixed.c
449+
return mixed.c
457450
if isinstance(mixed, sa.orm.util.AliasedClass):
458451
return sa.inspect(mixed).mapper.columns
459452
if isinstance(mixed, sa.orm.Mapper):
@@ -520,10 +513,7 @@ def quote(mixed, ident):
520513

521514

522515
def _get_query_compile_state(query):
523-
if hasattr(query, '_compile_state'):
524-
return query._compile_state()
525-
else: # SQLAlchemy <1.4
526-
return query
516+
return query._compile_state()
527517

528518

529519
def get_polymorphic_mappers(mixed):
@@ -878,7 +868,4 @@ def naturally_equivalent(obj, obj2):
878868

879869

880870
def _get_class_registry(class_):
881-
try:
882-
return class_.registry._class_registry
883-
except AttributeError: # SQLAlchemy <1.4
884-
return class_._decl_class_registry
871+
return class_.registry._class_registry

sqlalchemy_utils/functions/sort_query.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,7 @@ def make_order_by_deterministic(query):
4040
"""
4141
order_by_func = sa.asc
4242

43-
try:
44-
order_by_clauses = query._order_by_clauses
45-
except AttributeError: # SQLAlchemy <1.4
46-
order_by_clauses = query._order_by
43+
order_by_clauses = query._order_by_clauses
4744
if not order_by_clauses:
4845
column = None
4946
else:

sqlalchemy_utils/types/uuid.py

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,8 @@
33
from sqlalchemy import types, util
44
from sqlalchemy.dialects import mssql, postgresql
55

6-
from ..compat import get_sqlalchemy_version
76
from .scalar_coercible import ScalarCoercible
87

9-
sqlalchemy_version = get_sqlalchemy_version()
10-
118

129
class UUIDType(ScalarCoercible, types.TypeDecorator):
1310
"""
@@ -71,16 +68,8 @@ def _coerce(value):
7168

7269
return value
7370

74-
# sqlalchemy >= 1.4.30 quotes UUID's automatically.
75-
# It is only necessary to quote UUID's in sqlalchemy < 1.4.30.
76-
if sqlalchemy_version < (1, 4, 30):
77-
78-
def process_literal_param(self, value, dialect):
79-
return f"'{value}'" if value else value
80-
else:
81-
82-
def process_literal_param(self, value, dialect):
83-
return value
71+
def process_literal_param(self, value, dialect):
72+
return value
8473

8574
def process_bind_param(self, value, dialect):
8675
if value is None:

tests/functions/test_database.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,13 @@
22
import sqlalchemy as sa
33

44
from sqlalchemy_utils import create_database, database_exists, drop_database
5-
from sqlalchemy_utils.compat import get_sqlalchemy_version
65

76
pymysql = None
87
try:
98
import pymysql # noqa
109
except ImportError:
1110
pass
1211

13-
sqlalchemy_version = get_sqlalchemy_version()
14-
1512

1613
class DatabaseTest:
1714
def test_create_and_drop(self, dsn):
@@ -101,7 +98,6 @@ def dsn(self, postgresql_db_user, postgresql_db_password):
10198
)
10299

103100

104-
@pytest.mark.skipif('sqlalchemy_version < (2, 0, 0)')
105101
class TestDatabasePostgresPsycoPG3(DatabaseTest):
106102

107103
@pytest.fixture

tests/types/test_json.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,7 @@ def test_compilation(self, Document, session):
8282
def test_unhashable_type(self, AAA, BBB, session):
8383
"""Verify there are no TypeErrors with certain JSON queries.
8484
85-
This test will fail under these conditions:
86-
87-
1. sqlalchemy versions 1.4.19 through 1.4.23 are installed.
88-
2. `JSONType.hashable` is not set to False.
85+
This test will fail if `JSONType.hashable` is not set to False.
8986
9087
For more info, see:
9188

0 commit comments

Comments
 (0)