sqlalchemy icon indicating copy to clipboard operation
sqlalchemy copied to clipboard

Unexpected relationship kwarg with mypy from a mixin

Open Vafilor opened this issue 6 months ago • 2 comments

Ensure stubs packages are not installed

  • [X] No sqlalchemy stub packages is installed (both sqlalchemy-stubs and sqlalchemy2-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.

Vafilor avatar Aug 03 '24 21:08 Vafilor