Skip to content

Commit c687ea4

Browse files
Remove SQLAlchemy 1.x compatibility branches
With SQLAlchemy 2.0 required, types.DOUBLE, types.Double, and TypeEngine._variant_mapping always exist. Use them directly and drop the version-dependent test branches. Keep get_double_type as a public helper that returns types.DOUBLE. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 579ac3c commit c687ea4

6 files changed

Lines changed: 21 additions & 54 deletions

File tree

‎pyathena/sqlalchemy/array.py‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -222,8 +222,7 @@ def variant(self, type_: TypeEngine[Any]) -> TypeEngine[Any] | None:
222222
Returns:
223223
The variant type, or None when the type has no variant for this dialect.
224224
"""
225-
# SQLAlchemy 1.x types have no _variant_mapping.
226-
return getattr(type_, "_variant_mapping", {}).get(self.dialect.name)
225+
return type_._variant_mapping.get(self.dialect.name)
227226

228227
def decorator_impl(self, type_: types.TypeDecorator[Any]) -> TypeEngine[Any]:
229228
variant = self.variant(type_)

‎pyathena/sqlalchemy/base.py‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@
3838
AthenaMap,
3939
AthenaStruct,
4040
AthenaTimestamp,
41-
get_double_type,
4241
)
4342
from pyathena.sqlalchemy.util import _HashableDict, _split_type_arguments
4443
from pyathena.util import (
@@ -71,7 +70,7 @@
7170
ischema_names: dict[str, type[Any]] = {
7271
"boolean": types.BOOLEAN,
7372
"float": types.FLOAT,
74-
"double": get_double_type(),
73+
"double": types.DOUBLE,
7574
"real": types.FLOAT,
7675
"tinyint": TINYINT,
7776
"smallint": types.SMALLINT,

‎pyathena/sqlalchemy/compiler.py‎

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@
4545
AthenaMap,
4646
AthenaStruct,
4747
AthenaTimestamp,
48-
get_double_type,
4948
)
5049
from pyathena.sqlalchemy.util import _split_type_arguments
5150

@@ -608,7 +607,7 @@ def visit_truediv_binary(self, binary, operator, **kw):
608607
right_type = binary.right.type
609608

610609
if isinstance(left_type, types.Float) or isinstance(right_type, types.Float):
611-
division_type = get_double_type()()
610+
division_type: TypeEngine[Any] = types.DOUBLE()
612611
return (
613612
self.process(Cast(binary.left, division_type), **kw)
614613
+ " / "
@@ -629,7 +628,7 @@ def visit_truediv_binary(self, binary, operator, **kw):
629628
return (
630629
self.process(binary.left, **kw)
631630
+ " / "
632-
+ self.process(Cast(binary.right, get_double_type()()), **kw)
631+
+ self.process(Cast(binary.right, types.DOUBLE()), **kw)
633632
)
634633

635634
return super().visit_truediv_binary(binary, operator, **kw)
@@ -661,7 +660,7 @@ def visit_cast(self, cast: Cast[Any], **kwargs):
661660
type_clause = "CHAR"
662661
elif isinstance(type_, (types.LargeBinary, types.BINARY, types.VARBINARY)):
663662
type_clause = "VARBINARY"
664-
elif hasattr(types, "Double") and isinstance(type_, types.Double):
663+
elif isinstance(type_, types.Double):
665664
type_clause = "DOUBLE"
666665
elif isinstance(type_, (types.FLOAT, types.Float, types.REAL)):
667666
# https://docs.aws.amazon.com/athena/latest/ug/data-types.html
@@ -755,7 +754,7 @@ def _complex_dml_type(self, type_, *, require_precision=False, timestamp_precisi
755754
return "VARCHAR"
756755
if isinstance(type_, (types.LargeBinary, types.BINARY, types.VARBINARY)):
757756
return "VARBINARY"
758-
if isinstance(type_, getattr(types, "Double", get_double_type())):
757+
if isinstance(type_, types.Double):
759758
return "DOUBLE"
760759
if isinstance(type_, types.Float):
761760
return "REAL"

‎pyathena/sqlalchemy/types.py‎

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,18 +37,12 @@
3737

3838

3939
def get_double_type() -> type[Any]:
40-
"""Get the appropriate type for DOUBLE based on SQLAlchemy version.
41-
42-
SQLAlchemy 2.0+ provides a native DOUBLE type, while earlier versions
43-
only have FLOAT. This function returns the appropriate type based on
44-
what's available.
40+
"""Get the SQLAlchemy type for Athena DOUBLE.
4541
4642
Returns:
47-
types.DOUBLE for SQLAlchemy 2.0+, types.FLOAT for earlier versions.
43+
``types.DOUBLE``.
4844
"""
49-
if hasattr(types, "DOUBLE"):
50-
return types.DOUBLE
51-
return types.FLOAT
45+
return types.DOUBLE
5246

5347

5448
class AthenaBinary(types.LargeBinary):

‎tests/pyathena/sqlalchemy/test_base.py‎

Lines changed: 10 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
AthenaStruct,
3232
AthenaTimestamp,
3333
Tinyint,
34-
get_double_type,
3534
)
3635
from pyathena.util import RetryConfig
3736
from tests.pyathena.conftest import ENV
@@ -934,30 +933,13 @@ def test_reflect_table_with_schema(self, engine):
934933
def test_reflect_table_include_columns(self, engine):
935934
engine, conn = engine
936935
one_row_complex = Table("one_row_complex", MetaData(schema=ENV.schema))
937-
version = float(re.search(r"^([\d]+\.[\d]+)\..+", sqlalchemy.__version__).group(1))
938-
if version <= 1.2:
939-
engine.dialect.reflecttable(
940-
conn, one_row_complex, include_columns=["col_int"], exclude_columns=[]
941-
)
942-
elif version == 1.3:
943-
# https://docs.sqlalchemy.org/en/13/changelog/changelog_13.html#change-64ac776996da1a5c3e3460b4c0f0b257
944-
engine.dialect.reflecttable(
945-
conn,
946-
one_row_complex,
947-
include_columns=["col_int"],
948-
exclude_columns=[],
949-
resolve_fks=True,
950-
)
951-
else: # version >= 1.4
952-
# https://docs.sqlalchemy.org/en/14/changelog/changelog_14.html#change-0215fae622c01f9409eb1ba2754f4792
953-
# https://docs.sqlalchemy.org/en/14/core/reflection.html#sqlalchemy.engine.reflection.Inspector.reflect_table
954-
insp = sqlalchemy.inspect(engine)
955-
insp.reflect_table(
956-
one_row_complex,
957-
include_columns=["col_int"],
958-
exclude_columns=[],
959-
resolve_fks=True,
960-
)
936+
insp = sqlalchemy.inspect(engine)
937+
insp.reflect_table(
938+
one_row_complex,
939+
include_columns=["col_int"],
940+
exclude_columns=[],
941+
resolve_fks=True,
942+
)
961943
assert len(one_row_complex.c) == 1
962944
assert one_row_complex.c.col_int is not None
963945
pytest.raises(AttributeError, lambda: one_row_complex.c.col_tinyint)
@@ -1357,7 +1339,7 @@ def test_reflect_select(self, engine):
13571339
assert isinstance(one_row_complex.c.col_int.type, types.INTEGER)
13581340
assert isinstance(one_row_complex.c.col_bigint.type, types.BIGINT)
13591341
assert isinstance(one_row_complex.c.col_float.type, types.FLOAT)
1360-
assert isinstance(one_row_complex.c.col_double.type, get_double_type())
1342+
assert isinstance(one_row_complex.c.col_double.type, types.DOUBLE)
13611343
assert isinstance(one_row_complex.c.col_string.type, types.String)
13621344
assert isinstance(one_row_complex.c.col_varchar.type, types.VARCHAR)
13631345
assert one_row_complex.c.col_varchar.type.length == 10
@@ -1408,7 +1390,7 @@ def test_get_column_type(self, engine):
14081390
assert isinstance(dialect._get_column_type("int"), types.INTEGER)
14091391
assert isinstance(dialect._get_column_type("bigint"), types.BIGINT)
14101392
assert isinstance(dialect._get_column_type("float"), types.FLOAT)
1411-
assert isinstance(dialect._get_column_type("double"), get_double_type())
1393+
assert isinstance(dialect._get_column_type("double"), types.DOUBLE)
14121394
assert isinstance(dialect._get_column_type("real"), types.FLOAT)
14131395
assert isinstance(dialect._get_column_type("string"), types.String)
14141396
assert isinstance(dialect._get_column_type("varchar"), types.VARCHAR)
@@ -3265,9 +3247,7 @@ def test_numeric_type_variants(self, engine):
32653247
assert type(actual.c.col_integer2.type) in [types.INT, types.INTEGER, types.Integer]
32663248
assert type(actual.c.col_bigint.type) in [types.BIGINT, types.BigInteger]
32673249
assert type(actual.c.col_biginteger.type) in [types.BIGINT, types.BigInteger]
3268-
expected_double_types = [types.FLOAT, types.Float]
3269-
if hasattr(types, "DOUBLE"):
3270-
expected_double_types.extend([types.DOUBLE, types.Double, types.DOUBLE_PRECISION])
3250+
expected_double_types = [types.DOUBLE, types.Double, types.DOUBLE_PRECISION]
32713251
assert type(actual.c.col_double1.type) in expected_double_types
32723252
assert type(actual.c.col_double2.type) in expected_double_types
32733253
assert type(actual.c.col_double_precision.type) in expected_double_types

‎tests/pyathena/sqlalchemy/test_types.py‎

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,5 @@
1010
def test_get_double_type():
1111
from pyathena.sqlalchemy.base import ischema_names
1212

13-
result = get_double_type()
14-
if hasattr(types, "DOUBLE"):
15-
assert result is types.DOUBLE
16-
else:
17-
assert result is types.FLOAT
18-
assert ischema_names["double"] is result
13+
assert get_double_type() is types.DOUBLE
14+
assert ischema_names["double"] is types.DOUBLE

0 commit comments

Comments
 (0)