Problem
The get_query function in the SQLAlchemy adapter has two related type-safety issues:
1. SQLAlchemy 2.0 DeclarativeBase not supported
SQLAlchemy 2.0 introduced a new base class DeclarativeBase (replacing the legacy declarative_base() / DeclarativeMeta approach). Models defined with the new style:
from sqlalchemy.orm import DeclarativeBase
class Base(DeclarativeBase):
pass
class Resource(Base):
__tablename__ = "resource"
id: Mapped[int] = mapped_column(primary_key=True)
...do not inherit from DeclarativeMeta, so passing them as table to get_query currently raises an error on type checkers.
2. Bare Select return type loses type information
The return type is currently annotated as Select (unparameterised), which loses row-type information. Callers cannot benefit from type inference on query results.
Proposed fix
- Try-import
DeclarativeBase from sqlalchemy.orm (available in SQLAlchemy ≥ 2.0), falling back to a placeholder class for 1.4 compatibility, and include type[DeclarativeBase] in GenericTable.
- Add
@overload signatures for get_query so that when an ORM model class is passed, the return type resolves to Select[Tuple[T]], and when a core Table is passed it returns Select[Any].
- Add
from __future__ import annotations to keep the subscripted Select[...] syntax compatible with Python 3.8/SQLAlchemy 1.4.
I have a working patch ready and am happy to submit a PR once there is agreement on the approach.
Problem
The
get_queryfunction in the SQLAlchemy adapter has two related type-safety issues:1. SQLAlchemy 2.0
DeclarativeBasenot supportedSQLAlchemy 2.0 introduced a new base class
DeclarativeBase(replacing the legacydeclarative_base()/DeclarativeMetaapproach). Models defined with the new style:...do not inherit from
DeclarativeMeta, so passing them astabletoget_querycurrently raises an error on type checkers.2. Bare
Selectreturn type loses type informationThe return type is currently annotated as
Select(unparameterised), which loses row-type information. Callers cannot benefit from type inference on query results.Proposed fix
DeclarativeBasefromsqlalchemy.orm(available in SQLAlchemy ≥ 2.0), falling back to a placeholder class for 1.4 compatibility, and includetype[DeclarativeBase]inGenericTable.@overloadsignatures forget_queryso that when an ORM model class is passed, the return type resolves toSelect[Tuple[T]], and when a coreTableis passed it returnsSelect[Any].from __future__ import annotationsto keep the subscriptedSelect[...]syntax compatible with Python 3.8/SQLAlchemy 1.4.I have a working patch ready and am happy to submit a PR once there is agreement on the approach.