From: Mike Bayer Date: Mon, 21 Jun 2021 16:52:42 +0000 (-0400) Subject: accommodate no cls info found in _scan_declarative X-Git-Tag: rel_1_4_19~9^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6ca7c2eb5294c255b3c1f62ec1445e3e5d52d4ba;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git accommodate no cls info found in _scan_declarative Fixed issue in mypy plugin where class info for a custom declarative base would not be handled correctly on a cached mypy pass, leading to an AssertionError being raised. Fixes: #6476 Change-Id: If78340673e6a4d16d8f7cf787ce3bdb02c8bd47b --- diff --git a/doc/build/changelog/unreleased_14/6476.rst b/doc/build/changelog/unreleased_14/6476.rst new file mode 100644 index 0000000000..8f740f4a17 --- /dev/null +++ b/doc/build/changelog/unreleased_14/6476.rst @@ -0,0 +1,7 @@ +.. change:: + :tags: bug, mypy + :tickets: 6476 + + Fixed issue in mypy plugin where class info for a custom declarative base + would not be handled correctly on a cached mypy pass, leading to an + AssertionError being raised. diff --git a/lib/sqlalchemy/ext/mypy/decl_class.py b/lib/sqlalchemy/ext/mypy/decl_class.py index 2870eeb6fb..61737fd660 100644 --- a/lib/sqlalchemy/ext/mypy/decl_class.py +++ b/lib/sqlalchemy/ext/mypy/decl_class.py @@ -50,7 +50,10 @@ def _scan_declarative_assignments_and_apply_types( info = util._info_for_cls(cls, api) - if cls.fullname.startswith("builtins"): + if info is None: + # this can occur during cached passes + return None + elif cls.fullname.startswith("builtins"): return None elif "_sa_decl_class_applied" in info.metadata: cls_metadata = util.DeclClassApplied.deserialize( diff --git a/lib/sqlalchemy/ext/mypy/util.py b/lib/sqlalchemy/ext/mypy/util.py index 26bb0ac67a..67c3fa2091 100644 --- a/lib/sqlalchemy/ext/mypy/util.py +++ b/lib/sqlalchemy/ext/mypy/util.py @@ -208,6 +208,8 @@ def _info_for_cls( ) -> TypeInfo: if cls.info is CLASSDEF_NO_INFO: sym = api.lookup_qualified(cls.name, cls) + if sym is None: + return None assert sym and isinstance(sym.node, TypeInfo) return sym.node diff --git a/test/ext/mypy/incremental/ticket_6476/__init__.py b/test/ext/mypy/incremental/ticket_6476/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/ext/mypy/incremental/ticket_6476/base.py b/test/ext/mypy/incremental/ticket_6476/base.py new file mode 100644 index 0000000000..fc14e4719c --- /dev/null +++ b/test/ext/mypy/incremental/ticket_6476/base.py @@ -0,0 +1,8 @@ +from sqlalchemy.ext.declarative import declarative_base + + +class CustomBase: + x = 5 + + +sql_base = declarative_base(cls=CustomBase) diff --git a/test/ext/mypy/incremental/ticket_6476/patch1.testpatch b/test/ext/mypy/incremental/ticket_6476/patch1.testpatch new file mode 100644 index 0000000000..75a66c7a5e --- /dev/null +++ b/test/ext/mypy/incremental/ticket_6476/patch1.testpatch @@ -0,0 +1,7 @@ +--- a/table.py 2021-06-21 12:16:35.418148313 -0400 ++++ b/table.py 2021-06-21 12:16:31.204108368 -0400 +@@ -3,3 +3,4 @@ + class Table(sql_base): + pass + ++x = Table.x diff --git a/test/ext/mypy/incremental/ticket_6476/table.py b/test/ext/mypy/incremental/ticket_6476/table.py new file mode 100644 index 0000000000..bf971dba67 --- /dev/null +++ b/test/ext/mypy/incremental/ticket_6476/table.py @@ -0,0 +1,5 @@ +from .base import sql_base + + +class Table(sql_base): + pass