[Python] SQLAlchemy Mapped field not correctly type-checked

Discussão em 'Python' iniciado por Stack, Março 21, 2025.

  1. Stack

    Stack Membro Participativo

    With this code:

    from typing import Protocol
    from sqlalchemy import Integer
    from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column


    class SpamProt(Protocol):
    id: int


    class Base(DeclarativeBase):
    pass


    class SpamModel(Base):
    id: Mapped[int] = mapped_column(Integer())


    def do_with_spam(d: SpamProt) -> None:
    raise NotImplementedError()


    if __name__ == "__main__":
    spam = SpamModel(id=10)
    do_with_spam(spam)


    mypy is returning an error:

    spam.py:24: error: Argument 1 to "do_with_spam" has incompatible type "SpamModel"; expected "SpamProt" [arg-type]
    spam.py:24: note: Following member(s) of "SpamModel" have conflicts:
    spam.py:24: note: id: expected "int", got "Mapped[int]"
    Found 1 error in 1 file (checked 1 source file)


    As SQLAlchemy claims to have no fully compatible typing without any plugins, I don't understand why this simplest example doesn't work. It is not a result of invariance. It is not an effect of interference from old plugin (here's the whole environment):

    ╭───────────────────┬─────────┬──────────╮
    │ name │ version │ location │
    ├───────────────────┼─────────┼──────────┤
    │ greenlet │ 3.1.1 │ │
    │ mypy │ 1.15.0 │ │
    │ mypy-extensions │ 1.0.0 │ │
    │ SQLAlchemy │ 2.0.39 │ │
    │ typing_extensions │ 4.12.2 │ │
    ╰───────────────────┴─────────┴──────────╯


    do I fundamentally misunderstand how the Mapped arguments should work?

    Continue reading...

Compartilhe esta Página