SQLAlchemy 1.4 Typing Stubs
sqlalchemy2-stubs provides interim PEP-484 typing stubs specifically for the SQLAlchemy 1.4 release series. It is an alpha-level project designed to work with a Mypy extension, replacing the older 'sqlalchemy-stubs' package. The project aims to enhance static type checking for SQLAlchemy 1.4 applications, but it is explicitly incompatible with SQLAlchemy 2.0, which features native inline typing. The current version is 0.0.2a38, and its release cadence is tied to the needs of SQLAlchemy 1.4 typing support.
Warnings
- breaking The `sqlalchemy2-stubs` package is explicitly NOT compatible with SQLAlchemy 2.0. Upgrading to SQLAlchemy 2.0 requires manual uninstallation of `sqlalchemy2-stubs` because SQLAlchemy 2.0 includes inline type annotations that conflict with stub packages.
- deprecated The Mypy plugin associated with `sqlalchemy2-stubs` is deprecated in SQLAlchemy 2.0 and has known compatibility issues with Mypy versions 1.11.0 or greater, with support guaranteed only up to Mypy 1.10.1.
- gotcha Do not install `sqlalchemy2-stubs` and the older `sqlalchemy-stubs` (from Dropbox) simultaneously. They occupy the same namespace and will cause conflicts and incorrect type checking results.
- gotcha Mixed environments (e.g., SQLAlchemy 1.x and 2.x codebases, or incremental migration attempts) where `sqlalchemy2-stubs` is present can lead to significant type errors, especially with imports like `declarative_base`.
Install
-
pip install sqlalchemy2-stubs -
pip install 'sqlalchemy[mypy]' sqlalchemy2-stubs
Imports
- declarative_base
from sqlalchemy.ext.declarative import declarative_base
- Column
from sqlalchemy import Column
- Integer
from sqlalchemy import Integer
- String
from sqlalchemy import String
- Mapped
from sqlalchemy.orm import Mapped
Quickstart
from typing import Optional
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.orm import Mapped, declarative_base, Session
Base = declarative_base()
class User(Base):
__tablename__ = "users"
id: Mapped[int] = Column(Integer, primary_key=True)
name: Mapped[Optional[str]] = Column(String(50))
email: Mapped[str] = Column(String(50), nullable=False)
def __repr__(self) -> str:
return f"<User(id={self.id}, name='{self.name}', email='{self.email}')>"
# Example usage (not requiring sqlalchemy2-stubs at runtime, but for type checking)
if __name__ == '__main__':
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
with Session(engine) as session:
new_user = User(name='Alice', email='alice@example.com')
session.add(new_user)
session.commit()
print(f"Added user: {new_user}")
retrieved_user = session.query(User).filter_by(name='Alice').first()
print(f"Retrieved user: {retrieved_user}")