如何让 Mypy 识别不可为 null 的 ORM 属性?

Leo*_*hen 6 python sqlalchemy mypy

Mypy 将 ORM 不可为 null 的实例属性推断为可选。

文件名:test.py

from sqlalchemy.orm import decl_api, registry
from sqlalchemy import BigInteger, Column, String

mapper_registry = registry()


class Base(metaclass=decl_api.DeclarativeMeta):
    __abstract__ = True

    registry = mapper_registry
    metadata = mapper_registry.metadata

    __init__ = mapper_registry.constructor


class Person(Base):
    __tablename__ = "persons"

    id = Column(BigInteger, primary_key=True, autoincrement=True)
    name = Column(String(40), nullable=False)


def main(person: Person):
    person_id = person.id
    person_name = person.name

    reveal_locals()
Run Code Online (Sandbox Code Playgroud)

运行mypy test.py产量:

test.py:27: note: Revealed local types are:
test.py:27: note:     person: test.Person
test.py:27: note:     person_id: Union[builtins.int, None]
test.py:27: note:     person_name: Union[builtins.str, None]
Run Code Online (Sandbox Code Playgroud)

据我的理解,person_idperson_name应该分别是int和 ,str因为它们被设置为不可空。

我在这里缺少什么?


相关库:

SQLAlchemy         1.4.25
sqlalchemy2-stubs  0.0.2a15
mypy               0.910
mypy-extensions    0.4.3
Run Code Online (Sandbox Code Playgroud)

小智 1

nullable=False我在使用 mypy评估列时遇到了同样的问题。我的一位队友在 SqlAlchemy 文档中找到了答案:

\n

https://docs.sqlalchemy.org/en/14/orm/extensions/mypy.html#introspection-of-columns-based-on-typeengine

\n
\n

默认情况下,这些类型始终被视为可选,即使对于主键和不可为 null 的列也是如此。原因是因为虽然数据库列 \xe2\x80\x9cid\xe2\x80\x9d 和 \xe2\x80\x9cname\xe2\x80\x9d 可以\xe2\x80\x99t 为 NULL,但 Python\nattributes id 和如果没有显式的\n构造函数,名称肯定可以是 None:

\n
\n

他们在那篇文章中还列出了一些缓解措施,其中明确声明要映射的列类型。

\n