sqlalchemy
sqlalchemy copied to clipboard
Unexpected relationship kwarg with mypy from a mixin
Ensure stubs packages are not installed
- [X] No sqlalchemy stub packages is installed (both
sqlalchemy-stubs
andsqlalchemy2-stubs
are not compatible with v2)
Verify if the api is typed
- [X] The api is not in a module listed in #6810 so it should pass type checking
Describe the typing issue
An unexpected kwarg error is emitted by mypy when creating a class that uses a mixin with a relationship.
To Reproduce
from sqlalchemy import ForeignKey, create_engine
from sqlalchemy.orm import (
DeclarativeBase,
Mapped,
MappedAsDataclass,
Session,
declarative_mixin,
declared_attr,
mapped_column,
relationship,
)
class Base(MappedAsDataclass, DeclarativeBase):
pass
class User(Base):
__tablename__ = "users"
id: Mapped[int] = mapped_column(primary_key=True, init=False)
name: Mapped[str]
@declarative_mixin
class UserMixin:
user_id = mapped_column(ForeignKey("users.id"))
@declared_attr
def user(cls) -> Mapped["User"]:
return relationship("User", kw_only=True)
class Task(UserMixin, Base):
__tablename__ = "tasks"
id: Mapped[int] = mapped_column(primary_key=True, init=False)
name: Mapped[str]
# None is added as the return value to make sure mypy checks this
# From mypy: By default the bodies of untyped functions are not checked, consider using --check-untyped-defs [annotation-unchecked]
def main() -> None:
engine = create_engine("sqlite://", echo=True)
Base.metadata.create_all(engine)
with Session(engine) as session:
user = User(name="user")
# error: Unexpected keyword argument "user" for "Task" [call-arg]
task = Task(name="Submit issue", user=user)
session.add_all([user, task])
session.commit()
if __name__ == "__main__":
main()
Error
main.py:48: error: Unexpected keyword argument "user" for "Task" [call-arg]
Found 1 error in 1 file (checked 1 source file)
Versions
- OS: macOS 14.5
- Python: 3.12.2
- SQLAlchemy: 2.0.31
- Type checker (eg: mypy 0.991, pyright 1.1.290, etc): mypy: 1.11.1
Additional context
Repo here: https://github.com/Vafilor/sqlalchemy-mypy.
I appreciate you.