From ea844985d08ec6de49e82bb6a5878765bbeeb17b Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Thu, 18 Mar 2021 15:26:05 -0400 Subject: [PATCH] check for MemberExpr looking for column argument Fixed issue in MyPy extension which crashed on detecting the type of a :class:`.Column` if the type were given with a module prefix like ``sa.Integer()``. Fixes: sqlalchemy/sqlalchemy2-stubs/#2 Change-Id: I71f53a6ced501ae144e28ce255cf3f50ea2b2e84 --- doc/build/changelog/unreleased_14/stubs_2.rst | 8 +++++ lib/sqlalchemy/ext/mypy/decl_class.py | 2 +- test/ext/mypy/files/sa_module_prefix.py | 33 +++++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 doc/build/changelog/unreleased_14/stubs_2.rst create mode 100644 test/ext/mypy/files/sa_module_prefix.py diff --git a/doc/build/changelog/unreleased_14/stubs_2.rst b/doc/build/changelog/unreleased_14/stubs_2.rst new file mode 100644 index 0000000000..20689cbcf6 --- /dev/null +++ b/doc/build/changelog/unreleased_14/stubs_2.rst @@ -0,0 +1,8 @@ +.. change:: + :tags: bug, mypy + :tickets: sqlalchemy/sqlalchemy2-stubs/2 + + Fixed issue in MyPy extension which crashed on detecting the type of a + :class:`.Column` if the type were given with a module prefix like + ``sa.Integer()``. + diff --git a/lib/sqlalchemy/ext/mypy/decl_class.py b/lib/sqlalchemy/ext/mypy/decl_class.py index f5215ca1cf..7a0c251c3b 100644 --- a/lib/sqlalchemy/ext/mypy/decl_class.py +++ b/lib/sqlalchemy/ext/mypy/decl_class.py @@ -693,7 +693,7 @@ def _infer_type_from_decl_column( # x = Column(String(50)) callee = column_arg.callee break - elif isinstance(column_arg, nodes.NameExpr): + elif isinstance(column_arg, (nodes.NameExpr, nodes.MemberExpr)): if isinstance(column_arg.node, TypeInfo): # x = Column(String) callee = column_arg diff --git a/test/ext/mypy/files/sa_module_prefix.py b/test/ext/mypy/files/sa_module_prefix.py new file mode 100644 index 0000000000..a37ae6b06f --- /dev/null +++ b/test/ext/mypy/files/sa_module_prefix.py @@ -0,0 +1,33 @@ +from typing import List +from typing import Optional + +import sqlalchemy as sa +from sqlalchemy import orm as saorm + + +Base = saorm.declarative_base() + + +class B(Base): + __tablename__ = "b" + id = sa.Column(sa.Integer, primary_key=True) + a_id: int = sa.Column(sa.ForeignKey("a.id")) + data = sa.Column(sa.String) + + a: Optional["A"] = saorm.relationship("A", back_populates="bs") + + +class A(Base): + __tablename__ = "a" + + id = sa.Column(sa.Integer, primary_key=True) + data = sa.Column(sa.String) + bs = saorm.relationship(B, uselist=True, back_populates="a") + + +a1 = A(bs=[B(data="b"), B(data="b")]) + +x: List[B] = a1.bs + + +b1 = B(a=A()) -- 2.47.2