python - SQLAlchemy Mapped field not correctly type-checked - Stack Overflow

With this code:from typing import Protocolfrom sqlalchemy import Integerfrom sqlalchemy.orm import D

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?

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?

Share Improve this question edited Mar 21 at 9:19 InSync 11.1k4 gold badges18 silver badges56 bronze badges asked Mar 21 at 6:06 zefciuzefciu 2,0572 gold badges17 silver badges40 bronze badges 3
  • 1 Have you tried adding __ tablename __ and a primary key to the class then run it? – Sam Commented Mar 21 at 8:23
  • My problem is not with running the code, but with mypy static checks. Yes, the tablename is missing in this minimal example. My problem is that code like this does run as expected. The spam.id expression does return integer. Yet mypy doesn't accept this. – zefciu Commented Mar 21 at 8:42
  • 1 mypy doesn't execute any code. The only way it knows what list[int] means, for example, is because it's hard-coded in mypy itself what list means. Without a plugin, Mapped[int] is just an opaque string with no defined semantics. – chepner Commented Mar 24 at 11:27
Add a comment  | 

1 Answer 1

Reset to default -1

Adding the tablename and a primary key to the class solves your issue

class SpamModel(Base):
   __tablename__ = 'spam'
   id: Mapped[int] = mapped_column(Integer(), primary_key=True)
NotImplementedError

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744371019a4570951.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信