From: Mike Bayer Date: Wed, 1 Apr 2026 18:31:21 +0000 (-0400) Subject: update for mypy 1.20.0 X-Git-Tag: rel_2_0_49~4 X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=f50e07209e4706b8805ffe4e054758a34393b7da;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git update for mypy 1.20.0 Change-Id: I95f72b8a1818b79d01d26531202199f24fe3b808 (cherry picked from commit 120eb13e8e08d167fafd56590aaeb3c048f7afcc) --- diff --git a/lib/sqlalchemy/ext/hybrid.py b/lib/sqlalchemy/ext/hybrid.py index f9a9459bfb..cfcbb35a18 100644 --- a/lib/sqlalchemy/ext/hybrid.py +++ b/lib/sqlalchemy/ext/hybrid.py @@ -1436,7 +1436,7 @@ class hybrid_property(interfaces.InspectionAttrInfo, ORMDescriptor[_T]): name = self.__name__ break else: - name = attributes._UNKNOWN_ATTR_KEY # type: ignore[assignment] + name = attributes._UNKNOWN_ATTR_KEY # type: ignore[assignment,unused-ignore] # noqa: E501 return cast( "_HybridClassLevelAccessor[_T]", diff --git a/lib/sqlalchemy/ext/mutable.py b/lib/sqlalchemy/ext/mutable.py index 43967b784a..32525d9186 100644 --- a/lib/sqlalchemy/ext/mutable.py +++ b/lib/sqlalchemy/ext/mutable.py @@ -1038,7 +1038,7 @@ class MutableSet(Mutable, Set[_T]): self.symmetric_difference_update(other) return self - def __isub__(self, other: AbstractSet[object]) -> MutableSet[_T]: # type: ignore[misc] # noqa: E501 + def __isub__(self, other: AbstractSet[object]) -> MutableSet[_T]: # type: ignore[misc,unused-ignore] # noqa: E501 self.difference_update(other) return self @@ -1050,7 +1050,7 @@ class MutableSet(Mutable, Set[_T]): set.remove(self, elem) self.changed() - def discard(self, elem: _T) -> None: + def discard(self, elem: _T) -> None: # type: ignore[override,unused-ignore] # noqa: E501 set.discard(self, elem) self.changed() diff --git a/lib/sqlalchemy/sql/compiler.py b/lib/sqlalchemy/sql/compiler.py index 7819d51ba8..5efc232673 100644 --- a/lib/sqlalchemy/sql/compiler.py +++ b/lib/sqlalchemy/sql/compiler.py @@ -4569,6 +4569,8 @@ class SQLCompiler(Compiled): "_label_select_column is only relevant within " "the columns clause of a SELECT or RETURNING" ) + result_expr: Union[elements.Label[Any], _CompileLabel] + if isinstance(column, elements.Label): if col_expr is not column: result_expr = _CompileLabel( diff --git a/lib/sqlalchemy/testing/fixtures/mypy.py b/lib/sqlalchemy/testing/fixtures/mypy.py index 3cd5cbc2e2..2bed5fc328 100644 --- a/lib/sqlalchemy/testing/fixtures/mypy.py +++ b/lib/sqlalchemy/testing/fixtures/mypy.py @@ -202,15 +202,18 @@ class MypyTest(TestBase): expected_msg, ) - expected_msg = re.sub( - "List", "builtins.list", expected_msg - ) + # as of mypy 1.20.0 it's not spitting out + # "builtins" anymore (using assert_type() would be + # better overall) + # expected_msg = re.sub( + # "List", "builtins.list", expected_msg + # ) - expected_msg = re.sub( - r"\b(int|str|float|bool)\b", - lambda m: rf"builtins.{m.group(0)}\*?", - expected_msg, - ) + # expected_msg = re.sub( + # r"\b(int|str|float|bool)\b", + # lambda m: rf"builtins.{m.group(0)}\*?", + # expected_msg, + # ) # expected_msg = re.sub( # r"(Sequence|Tuple|List|Union)", # lambda m: fr"typing.{m.group(0)}\*?", diff --git a/lib/sqlalchemy/util/_py_collections.py b/lib/sqlalchemy/util/_py_collections.py index 5c5d2b13fa..ff94d3e04a 100644 --- a/lib/sqlalchemy/util/_py_collections.py +++ b/lib/sqlalchemy/util/_py_collections.py @@ -147,14 +147,14 @@ class immutabledict(ImmutableDictBase[_KT, _VT]): self, __value: Mapping[_KT, _VT] ) -> immutabledict[_KT, _VT]: return immutabledict( - super().__or__(__value), # type: ignore[call-overload] + super().__or__(__value), # type: ignore[call-overload,operator,unused-ignore] # noqa: E501 ) def __ror__( # type: ignore[override] self, __value: Mapping[_KT, _VT] ) -> immutabledict[_KT, _VT]: return immutabledict( - super().__ror__(__value), # type: ignore[call-overload] + super().__ror__(__value), # type: ignore[call-overload,operator,unused-ignore] # noqa: E501 ) @@ -198,7 +198,7 @@ class OrderedSet(Set[_T]): self._list.insert(pos, element) super().add(element) - def discard(self, element: _T) -> None: + def discard(self, element: _T) -> None: # type: ignore[override,unused-ignore] # noqa: E501 if element in self: self._list.remove(element) super().remove(element) @@ -248,7 +248,7 @@ class OrderedSet(Set[_T]): def __and__(self, other: AbstractSet[object]) -> OrderedSet[_T]: return self.intersection(other) - def symmetric_difference(self, other: Iterable[_T]) -> OrderedSet[_T]: + def symmetric_difference(self, other: Iterable[_T]) -> OrderedSet[_T]: # type: ignore[override,unused-ignore] # noqa: E501 collection: Collection[_T] if isinstance(other, set): collection = other_set = other @@ -271,7 +271,7 @@ class OrderedSet(Set[_T]): other_set = super().difference(*other) return self.__class__(a for a in self._list if a in other_set) - def __sub__(self, other: AbstractSet[Optional[_T]]) -> OrderedSet[_T]: + def __sub__(self, other: AbstractSet[Optional[_T]]) -> OrderedSet[_T]: # type: ignore[override,unused-ignore] # noqa: E501 return self.difference(other) def intersection_update(self, *other: Iterable[Any]) -> None: diff --git a/lib/sqlalchemy/util/typing.py b/lib/sqlalchemy/util/typing.py index 361cfac14f..b4875b68f7 100644 --- a/lib/sqlalchemy/util/typing.py +++ b/lib/sqlalchemy/util/typing.py @@ -469,7 +469,7 @@ def de_optionalize_union_types( else: typ.add(elem) - typ.discard(None) # type: ignore + typ.discard(None) # type: ignore[arg-type,unused-ignore] typ = {t for t in typ if t is not NoneType and not is_fwd_none(t)} diff --git a/pyproject.toml b/pyproject.toml index 719fc374b0..a4b998c8e1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -96,7 +96,7 @@ lint = [ mypy = [ {include-group = "tests-greenlet"}, - "mypy>=1.19.0", + "mypy>=1.20.0", "nox", # because we check noxfile.py "pytest>8,<10", # alembic/testing imports pytest "types-greenlet", diff --git a/test/typing/plain_files/ext/association_proxy/association_proxy_one.py b/test/typing/plain_files/ext/association_proxy/association_proxy_one.py index cb9f0b85d7..4e8e25af42 100644 --- a/test/typing/plain_files/ext/association_proxy/association_proxy_one.py +++ b/test/typing/plain_files/ext/association_proxy/association_proxy_one.py @@ -40,8 +40,8 @@ class Address(Base): u1 = User() if typing.TYPE_CHECKING: - # EXPECTED_RE_TYPE: sqlalchemy.*.associationproxy.AssociationProxyInstance\[builtins.set\*?\[builtins.str\]\] + # EXPECTED_RE_TYPE: sqlalchemy.*.associationproxy.AssociationProxyInstance\[set\*?\[str\]\] reveal_type(User.email_addresses) - # EXPECTED_RE_TYPE: builtins.set\*?\[builtins.str\] + # EXPECTED_RE_TYPE: set\*?\[str\] reveal_type(u1.email_addresses) diff --git a/test/typing/plain_files/ext/hybrid/hybrid_one.py b/test/typing/plain_files/ext/hybrid/hybrid_one.py index 52a2a19ed0..b294105437 100644 --- a/test/typing/plain_files/ext/hybrid/hybrid_one.py +++ b/test/typing/plain_files/ext/hybrid/hybrid_one.py @@ -66,19 +66,19 @@ stmt1 = select(Interval).where(expr1).where(expr4) stmt2 = select(expr4) if typing.TYPE_CHECKING: - # EXPECTED_RE_TYPE: builtins.int\*? + # EXPECTED_RE_TYPE: int\*? reveal_type(i1.length) - # EXPECTED_RE_TYPE: sqlalchemy.*._HybridClassLevelAccessor\[builtins.int\*?\] + # EXPECTED_RE_TYPE: sqlalchemy.*._HybridClassLevelAccessor\[int\*?\] reveal_type(Interval.length) - # EXPECTED_RE_TYPE: sqlalchemy.*.BinaryExpression\[builtins.bool\*?\] + # EXPECTED_RE_TYPE: sqlalchemy.*.BinaryExpression\[bool\*?\] reveal_type(expr1) - # EXPECTED_RE_TYPE: sqlalchemy.*.SQLCoreOperations\[builtins.int\*?\] + # EXPECTED_RE_TYPE: sqlalchemy.*.SQLCoreOperations\[int\*?\] reveal_type(expr2) - # EXPECTED_RE_TYPE: sqlalchemy.*.SQLCoreOperations\[builtins.int\*?\] + # EXPECTED_RE_TYPE: sqlalchemy.*.SQLCoreOperations\[int\*?\] reveal_type(expr3) # EXPECTED_TYPE: bool diff --git a/test/typing/plain_files/ext/hybrid/hybrid_two.py b/test/typing/plain_files/ext/hybrid/hybrid_two.py index b4f2aca769..25b0bfaa83 100644 --- a/test/typing/plain_files/ext/hybrid/hybrid_two.py +++ b/test/typing/plain_files/ext/hybrid/hybrid_two.py @@ -44,10 +44,10 @@ class Interval(Base): # while we are here, check some Float[] / div type stuff if typing.TYPE_CHECKING: - # EXPECTED_RE_TYPE: sqlalchemy.*Function\[builtins.float\*?\] + # EXPECTED_RE_TYPE: sqlalchemy.*Function\[float\*?\] reveal_type(f1) - # EXPECTED_RE_TYPE: sqlalchemy.*ColumnElement\[builtins.float\*?\] + # EXPECTED_RE_TYPE: sqlalchemy.*ColumnElement\[float\*?\] reveal_type(expr) return expr @@ -66,10 +66,10 @@ class Interval(Base): # while we are here, check some Float[] / div type stuff if typing.TYPE_CHECKING: - # EXPECTED_RE_TYPE: sqlalchemy.*Function\[builtins.float\*?\] + # EXPECTED_RE_TYPE: sqlalchemy.*Function\[float\*?\] reveal_type(f1) - # EXPECTED_RE_TYPE: sqlalchemy.*ColumnElement\[builtins.float\*?\] + # EXPECTED_RE_TYPE: sqlalchemy.*ColumnElement\[float\*?\] reveal_type(expr) return expr @@ -92,37 +92,37 @@ expr3n = Interval.new_radius.in_([0.5, 5.2]) if typing.TYPE_CHECKING: - # EXPECTED_RE_TYPE: builtins.int\*? + # EXPECTED_RE_TYPE: int\*? reveal_type(i1.length) - # EXPECTED_RE_TYPE: builtins.float\*? + # EXPECTED_RE_TYPE: float\*? reveal_type(i2.old_radius) - # EXPECTED_RE_TYPE: builtins.float\*? + # EXPECTED_RE_TYPE: float\*? reveal_type(i2.new_radius) - # EXPECTED_RE_TYPE: sqlalchemy.*._HybridClassLevelAccessor\[builtins.int\*?\] + # EXPECTED_RE_TYPE: sqlalchemy.*._HybridClassLevelAccessor\[int\*?\] reveal_type(Interval.length) - # EXPECTED_RE_TYPE: sqlalchemy.*._HybridClassLevelAccessor\[builtins.float\*?\] + # EXPECTED_RE_TYPE: sqlalchemy.*._HybridClassLevelAccessor\[float\*?\] reveal_type(Interval.old_radius) - # EXPECTED_RE_TYPE: sqlalchemy.*._HybridClassLevelAccessor\[builtins.float\*?\] + # EXPECTED_RE_TYPE: sqlalchemy.*._HybridClassLevelAccessor\[float\*?\] reveal_type(Interval.new_radius) - # EXPECTED_RE_TYPE: sqlalchemy.*.BinaryExpression\[builtins.bool\*?\] + # EXPECTED_RE_TYPE: sqlalchemy.*.BinaryExpression\[bool\*?\] reveal_type(expr1) - # EXPECTED_RE_TYPE: sqlalchemy.*._HybridClassLevelAccessor\[builtins.float\*?\] + # EXPECTED_RE_TYPE: sqlalchemy.*._HybridClassLevelAccessor\[float\*?\] reveal_type(expr2o) - # EXPECTED_RE_TYPE: sqlalchemy.*._HybridClassLevelAccessor\[builtins.float\*?\] + # EXPECTED_RE_TYPE: sqlalchemy.*._HybridClassLevelAccessor\[float\*?\] reveal_type(expr2n) - # EXPECTED_RE_TYPE: sqlalchemy.*.BinaryExpression\[builtins.bool\*?\] + # EXPECTED_RE_TYPE: sqlalchemy.*.BinaryExpression\[bool\*?\] reveal_type(expr3o) - # EXPECTED_RE_TYPE: sqlalchemy.*.BinaryExpression\[builtins.bool\*?\] + # EXPECTED_RE_TYPE: sqlalchemy.*.BinaryExpression\[bool\*?\] reveal_type(expr3n) # test #9268 diff --git a/test/typing/plain_files/ext/indexable.py b/test/typing/plain_files/ext/indexable.py index 314f4f99f0..20f0a0590a 100644 --- a/test/typing/plain_files/ext/indexable.py +++ b/test/typing/plain_files/ext/indexable.py @@ -41,7 +41,7 @@ a = Article( # EXPECTED_TYPE: str reveal_type(a.topic) -# EXPECTED_RE_TYPE: sqlalchemy.*._HybridClassLevelAccessor\[builtins.str\*?\] +# EXPECTED_RE_TYPE: sqlalchemy.*._HybridClassLevelAccessor\[str\*?\] reveal_type(Article.topic) # EXPECTED_TYPE: date diff --git a/test/typing/plain_files/ext/orderinglist/orderinglist_one.py b/test/typing/plain_files/ext/orderinglist/orderinglist_one.py index d2b7c5ece0..390f9d77e8 100644 --- a/test/typing/plain_files/ext/orderinglist/orderinglist_one.py +++ b/test/typing/plain_files/ext/orderinglist/orderinglist_one.py @@ -50,5 +50,5 @@ if TYPE_CHECKING: # EXPECTED_RE_TYPE: def \(\) -> sqlalchemy.*.orderinglist.OrderingList\[orderinglist_one.Bullet\] reveal_type(pos_from_text) - # EXPECTED_TYPE: builtins.list[orderinglist_one.Bullet] + # EXPECTED_TYPE: list[orderinglist_one.Bullet] reveal_type(slide.bullets) diff --git a/test/typing/plain_files/orm/dataclass_transforms_one.py b/test/typing/plain_files/orm/dataclass_transforms_one.py index 986483d8ef..c4e211adb2 100644 --- a/test/typing/plain_files/orm/dataclass_transforms_one.py +++ b/test/typing/plain_files/orm/dataclass_transforms_one.py @@ -28,7 +28,7 @@ tis = TestInitialSupport(data="some data", y=5) # EXPECTED_TYPE: str reveal_type(tis.data) -# EXPECTED_RE_TYPE: .*builtins.int \| None +# EXPECTED_RE_TYPE: .*int \| None reveal_type(tis.y) tis.data = "some other data" diff --git a/test/typing/plain_files/orm/relationship.py b/test/typing/plain_files/orm/relationship.py index daf8ddb37d..71d0622e68 100644 --- a/test/typing/plain_files/orm/relationship.py +++ b/test/typing/plain_files/orm/relationship.py @@ -131,34 +131,34 @@ class Engineer(Employee): if typing.TYPE_CHECKING: - # EXPECTED_RE_TYPE: sqlalchemy.*.InstrumentedAttribute\[builtins.str \| None\] + # EXPECTED_RE_TYPE: sqlalchemy.*.InstrumentedAttribute\[str \| None\] reveal_type(User.extra) - # EXPECTED_RE_TYPE: sqlalchemy.*.InstrumentedAttribute\[builtins.str \| None\] + # EXPECTED_RE_TYPE: sqlalchemy.*.InstrumentedAttribute\[str \| None\] reveal_type(User.extra_name) - # EXPECTED_RE_TYPE: sqlalchemy.*.InstrumentedAttribute\[builtins.str\*?\] + # EXPECTED_RE_TYPE: sqlalchemy.*.InstrumentedAttribute\[str\*?\] reveal_type(Address.email) - # EXPECTED_RE_TYPE: sqlalchemy.*.InstrumentedAttribute\[builtins.str\*?\] + # EXPECTED_RE_TYPE: sqlalchemy.*.InstrumentedAttribute\[str\*?\] reveal_type(Address.email_name) - # EXPECTED_RE_TYPE: sqlalchemy.*.InstrumentedAttribute\[builtins.list\*?\[relationship.Address\]\] + # EXPECTED_RE_TYPE: sqlalchemy.*.InstrumentedAttribute\[list\*?\[relationship.Address\]\] reveal_type(User.addresses_style_one) - # EXPECTED_RE_TYPE: sqlalchemy.orm.attributes.InstrumentedAttribute\[builtins.set\*?\[relationship.Address\]\] + # EXPECTED_RE_TYPE: sqlalchemy.orm.attributes.InstrumentedAttribute\[set\*?\[relationship.Address\]\] reveal_type(User.addresses_style_two) - # EXPECTED_RE_TYPE: sqlalchemy.*.InstrumentedAttribute\[builtins.list\*?\[relationship.User\]\] + # EXPECTED_RE_TYPE: sqlalchemy.*.InstrumentedAttribute\[list\*?\[relationship.User\]\] reveal_type(Group.addresses_style_one_anno_only) - # EXPECTED_RE_TYPE: sqlalchemy.orm.attributes.InstrumentedAttribute\[builtins.set\*?\[relationship.User\]\] + # EXPECTED_RE_TYPE: sqlalchemy.orm.attributes.InstrumentedAttribute\[set\*?\[relationship.User\]\] reveal_type(Group.addresses_style_two_anno_only) - # EXPECTED_RE_TYPE: sqlalchemy.*.InstrumentedAttribute\[builtins.list\*?\[relationship.MoreMail\]\] + # EXPECTED_RE_TYPE: sqlalchemy.*.InstrumentedAttribute\[list\*?\[relationship.MoreMail\]\] reveal_type(Address.rel_style_one) - # EXPECTED_RE_TYPE: sqlalchemy.*.InstrumentedAttribute\[builtins.set\*?\[relationship.MoreMail\]\] + # EXPECTED_RE_TYPE: sqlalchemy.*.InstrumentedAttribute\[set\*?\[relationship.MoreMail\]\] reveal_type(Address.rel_style_one_anno_only) # EXPECTED_RE_TYPE: sqlalchemy.*.QueryableAttribute\[relationship.Engineer\] diff --git a/test/typing/plain_files/orm/session.py b/test/typing/plain_files/orm/session.py index 43fb17a754..5513dd7e5d 100644 --- a/test/typing/plain_files/orm/session.py +++ b/test/typing/plain_files/orm/session.py @@ -55,7 +55,7 @@ with Session(e) as sess: rows1 = q.all() - # EXPECTED_RE_TYPE: builtins.[Ll]ist\[.*User\*?\] + # EXPECTED_RE_TYPE: [Ll]ist\[.*User\*?\] reveal_type(rows1) q2 = sess.query(User.id).filter_by(id=7) diff --git a/test/typing/plain_files/orm/trad_relationship_uselist.py b/test/typing/plain_files/orm/trad_relationship_uselist.py index e15fe70934..27b08763ec 100644 --- a/test/typing/plain_files/orm/trad_relationship_uselist.py +++ b/test/typing/plain_files/orm/trad_relationship_uselist.py @@ -99,10 +99,10 @@ class Address(Base): if typing.TYPE_CHECKING: - # EXPECTED_RE_TYPE: sqlalchemy.*.InstrumentedAttribute\[builtins.list\*?\[trad_relationship_uselist.Address\]\] + # EXPECTED_RE_TYPE: sqlalchemy.*.InstrumentedAttribute\[list\*?\[trad_relationship_uselist.Address\]\] reveal_type(User.addresses_style_one) - # EXPECTED_RE_TYPE: sqlalchemy.*.InstrumentedAttribute\[builtins.set\*?\[trad_relationship_uselist.Address\]\] + # EXPECTED_RE_TYPE: sqlalchemy.*.InstrumentedAttribute\[set\*?\[trad_relationship_uselist.Address\]\] reveal_type(User.addresses_style_two) # EXPECTED_RE_TYPE: sqlalchemy.*.InstrumentedAttribute\[Any\] @@ -139,5 +139,5 @@ if typing.TYPE_CHECKING: # EXPECTED_RE_TYPE: sqlalchemy.*.InstrumentedAttribute\[Any\] reveal_type(Address.user_style_ten) - # EXPECTED_RE_TYPE: sqlalchemy.*.InstrumentedAttribute\[builtins.dict\*?\[builtins.str, trad_relationship_uselist.User\]\] + # EXPECTED_RE_TYPE: sqlalchemy.*.InstrumentedAttribute\[dict\*?\[str, trad_relationship_uselist.User\]\] reveal_type(Address.user_style_ten_typed) diff --git a/test/typing/plain_files/orm/traditional_relationship.py b/test/typing/plain_files/orm/traditional_relationship.py index bd6bada528..b87e0524c1 100644 --- a/test/typing/plain_files/orm/traditional_relationship.py +++ b/test/typing/plain_files/orm/traditional_relationship.py @@ -7,8 +7,10 @@ if no uselists are present. """ import typing +from typing import assert_type from typing import List from typing import Set +from typing import TYPE_CHECKING from sqlalchemy import ForeignKey from sqlalchemy import Integer @@ -19,6 +21,10 @@ from sqlalchemy.orm import mapped_column from sqlalchemy.orm import relationship +if TYPE_CHECKING: + from sqlalchemy.orm import InstrumentedAttribute + + class Base(DeclarativeBase): pass @@ -80,11 +86,9 @@ class Address(Base): if typing.TYPE_CHECKING: - # EXPECTED_RE_TYPE: sqlalchemy.*.InstrumentedAttribute\[builtins.list\*?\[traditional_relationship.Address\]\] - reveal_type(User.addresses_style_one) + assert_type(User.addresses_style_one, InstrumentedAttribute[list[Address]]) - # EXPECTED_RE_TYPE: sqlalchemy.*.InstrumentedAttribute\[builtins.set\*?\[traditional_relationship.Address\]\] - reveal_type(User.addresses_style_two) + assert_type(User.addresses_style_two, InstrumentedAttribute[set[Address]]) # EXPECTED_RE_TYPE: sqlalchemy.*.InstrumentedAttribute\[Any\] reveal_type(Address.user_style_one) @@ -98,11 +102,9 @@ if typing.TYPE_CHECKING: # EXPECTED_RE_TYPE: sqlalchemy.*.InstrumentedAttribute\[traditional_relationship.User\*?\] reveal_type(Address.user_style_two_typed) - # EXPECTED_RE_TYPE: sqlalchemy.*.InstrumentedAttribute\[builtins.list\*?\[traditional_relationship.User\]\] - reveal_type(Address.user_style_three) + assert_type(Address.user_style_three, InstrumentedAttribute[list[User]]) - # EXPECTED_RE_TYPE: sqlalchemy.*.InstrumentedAttribute\[builtins.list\*?\[traditional_relationship.User\]\] - reveal_type(Address.user_style_four) + assert_type(Address.user_style_four, InstrumentedAttribute[list[User]]) # EXPECTED_RE_TYPE: sqlalchemy.*.InstrumentedAttribute\[Any\] reveal_type(Address.user_style_five) diff --git a/test/typing/plain_files/orm/typed_queries.py b/test/typing/plain_files/orm/typed_queries.py index 3a190dba9f..677a79069e 100644 --- a/test/typing/plain_files/orm/typed_queries.py +++ b/test/typing/plain_files/orm/typed_queries.py @@ -3,6 +3,7 @@ from __future__ import annotations from typing import assert_type from typing import Optional from typing import Tuple +from typing import TYPE_CHECKING from sqlalchemy import Column from sqlalchemy import column @@ -27,6 +28,11 @@ from sqlalchemy.orm import mapped_column from sqlalchemy.orm import Session +if TYPE_CHECKING: + from sqlalchemy import Row + from sqlalchemy.orm.query import RowReturningQuery + + class Base(DeclarativeBase): pass @@ -140,9 +146,7 @@ def t_legacy_query_single_entity() -> None: # EXPECTED_TYPE: List[User] reveal_type(q1.all()) - # mypy switches to builtins.list for some reason here - # EXPECTED_RE_TYPE: .*\.[Ll]ist\[.*Row\*?\[Tuple\[.*User\]\]\] - reveal_type(q1.only_return_tuples(True).all()) + assert_type(q1.only_return_tuples(True).all(), list[Row[tuple[User]]]) # EXPECTED_TYPE: List[Tuple[User]] reveal_type(q1.tuples().all()) @@ -151,8 +155,7 @@ def t_legacy_query_single_entity() -> None: def t_legacy_query_cols_1() -> None: q1 = session.query(User.id, User.name).filter(User.id == 5) - # EXPECTED_TYPE: RowReturningQuery[Tuple[int, str]] - reveal_type(q1) + assert_type(q1, RowReturningQuery[tuple[int, str]]) # EXPECTED_TYPE: Row[Tuple[int, str]] reveal_type(q1.one()) diff --git a/test/typing/plain_files/sql/sql_operations.py b/test/typing/plain_files/sql/sql_operations.py index f0025b2cb3..278e2c9a88 100644 --- a/test/typing/plain_files/sql/sql_operations.py +++ b/test/typing/plain_files/sql/sql_operations.py @@ -121,34 +121,34 @@ if typing.TYPE_CHECKING: # as far as if this is ColumnElement, BinaryElement, SQLCoreOperations, # that might change. main thing is it's SomeSQLColThing[bool] and # not 'bool' or 'Any'. - # EXPECTED_RE_TYPE: sqlalchemy..*ColumnElement\[builtins.bool\] + # EXPECTED_RE_TYPE: sqlalchemy..*ColumnElement\[bool\] reveal_type(expr1) - # EXPECTED_RE_TYPE: sqlalchemy..*ColumnClause\[builtins.str.?\] + # EXPECTED_RE_TYPE: sqlalchemy..*ColumnClause\[str.?\] reveal_type(c1) - # EXPECTED_RE_TYPE: sqlalchemy..*ColumnClause\[builtins.int.?\] + # EXPECTED_RE_TYPE: sqlalchemy..*ColumnClause\[int.?\] reveal_type(c2) - # EXPECTED_RE_TYPE: sqlalchemy..*BinaryExpression\[builtins.bool\] + # EXPECTED_RE_TYPE: sqlalchemy..*BinaryExpression\[bool\] reveal_type(expr2) - # EXPECTED_RE_TYPE: sqlalchemy..*ColumnElement\[builtins.float | .*\.Decimal\] + # EXPECTED_RE_TYPE: sqlalchemy..*ColumnElement\[float | .*\.Decimal\] reveal_type(expr3) - # EXPECTED_RE_TYPE: sqlalchemy..*UnaryExpression\[builtins.int.?\] + # EXPECTED_RE_TYPE: sqlalchemy..*UnaryExpression\[int.?\] reveal_type(expr4) - # EXPECTED_RE_TYPE: sqlalchemy..*ColumnElement\[builtins.bool.?\] + # EXPECTED_RE_TYPE: sqlalchemy..*ColumnElement\[bool.?\] reveal_type(expr5) - # EXPECTED_RE_TYPE: sqlalchemy..*ColumnElement\[builtins.bool.?\] + # EXPECTED_RE_TYPE: sqlalchemy..*ColumnElement\[bool.?\] reveal_type(expr6) - # EXPECTED_RE_TYPE: sqlalchemy..*ColumnElement\[builtins.str\] + # EXPECTED_RE_TYPE: sqlalchemy..*ColumnElement\[str\] reveal_type(expr7) - # EXPECTED_RE_TYPE: sqlalchemy..*ColumnElement\[builtins.int.?\] + # EXPECTED_RE_TYPE: sqlalchemy..*ColumnElement\[int.?\] reveal_type(expr8) # EXPECTED_TYPE: BinaryExpression[bool] diff --git a/test/typing/plain_files/sql/typed_results.py b/test/typing/plain_files/sql/typed_results.py index 6e2fe89a30..48dc5fa352 100644 --- a/test/typing/plain_files/sql/typed_results.py +++ b/test/typing/plain_files/sql/typed_results.py @@ -88,12 +88,12 @@ reveal_type(async_session) single_stmt = select(User.name).where(User.name == "foo") -# EXPECTED_RE_TYPE: sqlalchemy..*Select\*?\[Tuple\[builtins.str\*?\]\] +# EXPECTED_RE_TYPE: sqlalchemy..*Select\*?\[Tuple\[str\*?\]\] reveal_type(single_stmt) multi_stmt = select(User.id, User.name).where(User.name == "foo") -# EXPECTED_RE_TYPE: sqlalchemy..*Select\*?\[Tuple\[builtins.int\*?, builtins.str\*?\]\] +# EXPECTED_RE_TYPE: sqlalchemy..*Select\*?\[Tuple\[int\*?, str\*?\]\] reveal_type(multi_stmt) @@ -144,7 +144,7 @@ def t_entity_varieties() -> None: r1 = session.execute(s1) - # EXPECTED_RE_TYPE: sqlalchemy..*.Result\[Tuple\[builtins.int\*?, typed_results.User\*?, builtins.str\*?\]\] + # EXPECTED_RE_TYPE: sqlalchemy..*.Result\[Tuple\[int\*?, typed_results.User\*?, str\*?\]\] reveal_type(r1) s2 = select(User, a1).where(User.name == "foo") @@ -167,7 +167,7 @@ def t_entity_varieties() -> None: # automatically typed since they are dynamically generated a1_id = cast(Mapped[int], a1.id) s3 = select(User.id, a1_id, a1, User).where(User.name == "foo") - # EXPECTED_RE_TYPE: sqlalchemy.*Select\*?\[Tuple\[builtins.int\*?, builtins.int\*?, typed_results.User\*?, typed_results.User\*?\]\] + # EXPECTED_RE_TYPE: sqlalchemy.*Select\*?\[Tuple\[int\*?, int\*?, typed_results.User\*?, typed_results.User\*?\]\] reveal_type(s3) # testing Mapped[entity] @@ -187,7 +187,7 @@ def t_entity_varieties() -> None: s5 = select(x, y, User.name + "hi") - # EXPECTED_RE_TYPE: sqlalchemy..*Select\*?\[Tuple\[builtins.int\*?, builtins.int\*?\, builtins.str\*?]\] + # EXPECTED_RE_TYPE: sqlalchemy..*Select\*?\[Tuple\[int\*?, int\*?\, str\*?]\] reveal_type(s5) @@ -231,27 +231,27 @@ def t_result_scalar_accessors() -> None: r1 = result.scalar() - # EXPECTED_RE_TYPE: builtins.str \| None + # EXPECTED_RE_TYPE: str \| None reveal_type(r1) r2 = result.scalar_one() - # EXPECTED_RE_TYPE: builtins.str\*? + # EXPECTED_RE_TYPE: str\*? reveal_type(r2) r3 = result.scalar_one_or_none() - # EXPECTED_RE_TYPE: builtins.str \| None + # EXPECTED_RE_TYPE: str \| None reveal_type(r3) r4 = result.scalars() - # EXPECTED_RE_TYPE: sqlalchemy..*ScalarResult\[builtins.str.*?\] + # EXPECTED_RE_TYPE: sqlalchemy..*ScalarResult\[str.*?\] reveal_type(r4) r5 = result.scalars(0) - # EXPECTED_RE_TYPE: sqlalchemy..*ScalarResult\[builtins.str.*?\] + # EXPECTED_RE_TYPE: sqlalchemy..*ScalarResult\[str.*?\] reveal_type(r5) @@ -260,27 +260,27 @@ async def t_async_result_scalar_accessors() -> None: r1 = await result.scalar() - # EXPECTED_RE_TYPE: builtins.str \| None + # EXPECTED_RE_TYPE: str \| None reveal_type(r1) r2 = await result.scalar_one() - # EXPECTED_RE_TYPE: builtins.str\*? + # EXPECTED_RE_TYPE: str\*? reveal_type(r2) r3 = await result.scalar_one_or_none() - # EXPECTED_RE_TYPE: builtins.str \| None + # EXPECTED_RE_TYPE: str \| None reveal_type(r3) r4 = result.scalars() - # EXPECTED_RE_TYPE: sqlalchemy..*ScalarResult\[builtins.str.*?\] + # EXPECTED_RE_TYPE: sqlalchemy..*ScalarResult\[str.*?\] reveal_type(r4) r5 = result.scalars(0) - # EXPECTED_RE_TYPE: sqlalchemy..*ScalarResult\[builtins.str.*?\] + # EXPECTED_RE_TYPE: sqlalchemy..*ScalarResult\[str.*?\] reveal_type(r5) @@ -355,336 +355,336 @@ async def t_async_result_insertmanyvalues_scalars() -> None: def t_connection_execute_multi_row_t() -> None: result = connection.execute(multi_stmt) - # EXPECTED_RE_TYPE: sqlalchemy.*CursorResult\[Tuple\[builtins.int\*?, builtins.str\*?\]\] + # EXPECTED_RE_TYPE: sqlalchemy.*CursorResult\[Tuple\[int\*?, str\*?\]\] reveal_type(result) row = result.one() - # EXPECTED_RE_TYPE: sqlalchemy.*Row\[Tuple\[builtins.int\*?, builtins.str\*?\]\] + # EXPECTED_RE_TYPE: sqlalchemy.*Row\[Tuple\[int\*?, str\*?\]\] reveal_type(row) x, y = row.t - # EXPECTED_RE_TYPE: builtins.int\*? + # EXPECTED_RE_TYPE: int\*? reveal_type(x) - # EXPECTED_RE_TYPE: builtins.str\*? + # EXPECTED_RE_TYPE: str\*? reveal_type(y) def t_connection_execute_multi() -> None: result = connection.execute(multi_stmt).t - # EXPECTED_RE_TYPE: sqlalchemy.*TupleResult\[Tuple\[builtins.int\*?, builtins.str\*?\]\] + # EXPECTED_RE_TYPE: sqlalchemy.*TupleResult\[Tuple\[int\*?, str\*?\]\] reveal_type(result) row = result.one() - # EXPECTED_RE_TYPE: Tuple\[builtins.int\*?, builtins.str\*?\] + # EXPECTED_RE_TYPE: Tuple\[int\*?, str\*?\] reveal_type(row) x, y = row - # EXPECTED_RE_TYPE: builtins.int\*? + # EXPECTED_RE_TYPE: int\*? reveal_type(x) - # EXPECTED_RE_TYPE: builtins.str\*? + # EXPECTED_RE_TYPE: str\*? reveal_type(y) def t_connection_execute_single() -> None: result = connection.execute(single_stmt).t - # EXPECTED_RE_TYPE: sqlalchemy.*TupleResult\[Tuple\[builtins.str\*?\]\] + # EXPECTED_RE_TYPE: sqlalchemy.*TupleResult\[Tuple\[str\*?\]\] reveal_type(result) row = result.one() - # EXPECTED_RE_TYPE: Tuple\[builtins.str\*?\] + # EXPECTED_RE_TYPE: Tuple\[str\*?\] reveal_type(row) (x,) = row - # EXPECTED_RE_TYPE: builtins.str\*? + # EXPECTED_RE_TYPE: str\*? reveal_type(x) def t_connection_execute_single_row_scalar() -> None: result = connection.execute(single_stmt).t - # EXPECTED_RE_TYPE: sqlalchemy.*TupleResult\[Tuple\[builtins.str\*?\]\] + # EXPECTED_RE_TYPE: sqlalchemy.*TupleResult\[Tuple\[str\*?\]\] reveal_type(result) x = result.scalar() - # EXPECTED_RE_TYPE: builtins.str \| None + # EXPECTED_RE_TYPE: str \| None reveal_type(x) def t_connection_scalar() -> None: obj = connection.scalar(single_stmt) - # EXPECTED_RE_TYPE: builtins.str \| None + # EXPECTED_RE_TYPE: str \| None reveal_type(obj) def t_connection_scalars() -> None: result = connection.scalars(single_stmt) - # EXPECTED_RE_TYPE: sqlalchemy.*ScalarResult\[builtins.str\*?\] + # EXPECTED_RE_TYPE: sqlalchemy.*ScalarResult\[str\*?\] reveal_type(result) data = result.all() - # EXPECTED_RE_TYPE: typing.Sequence\[builtins.str\*?\] + # EXPECTED_RE_TYPE: typing.Sequence\[str\*?\] reveal_type(data) def t_session_execute_multi() -> None: result = session.execute(multi_stmt).t - # EXPECTED_RE_TYPE: sqlalchemy.*TupleResult\[Tuple\[builtins.int\*?, builtins.str\*?\]\] + # EXPECTED_RE_TYPE: sqlalchemy.*TupleResult\[Tuple\[int\*?, str\*?\]\] reveal_type(result) row = result.one() - # EXPECTED_RE_TYPE: Tuple\[builtins.int\*?, builtins.str\*?\] + # EXPECTED_RE_TYPE: Tuple\[int\*?, str\*?\] reveal_type(row) x, y = row - # EXPECTED_RE_TYPE: builtins.int\*? + # EXPECTED_RE_TYPE: int\*? reveal_type(x) - # EXPECTED_RE_TYPE: builtins.str\*? + # EXPECTED_RE_TYPE: str\*? reveal_type(y) def t_session_execute_single() -> None: result = session.execute(single_stmt).t - # EXPECTED_RE_TYPE: sqlalchemy.*TupleResult\[Tuple\[builtins.str\*?\]\] + # EXPECTED_RE_TYPE: sqlalchemy.*TupleResult\[Tuple\[str\*?\]\] reveal_type(result) row = result.one() - # EXPECTED_RE_TYPE: Tuple\[builtins.str\*?\] + # EXPECTED_RE_TYPE: Tuple\[str\*?\] reveal_type(row) (x,) = row - # EXPECTED_RE_TYPE: builtins.str\*? + # EXPECTED_RE_TYPE: str\*? reveal_type(x) def t_session_scalar() -> None: obj = session.scalar(single_stmt) - # EXPECTED_RE_TYPE: builtins.str \| None + # EXPECTED_RE_TYPE: str \| None reveal_type(obj) def t_session_scalars() -> None: result = session.scalars(single_stmt) - # EXPECTED_RE_TYPE: sqlalchemy.*ScalarResult\[builtins.str\*?\] + # EXPECTED_RE_TYPE: sqlalchemy.*ScalarResult\[str\*?\] reveal_type(result) data = result.all() - # EXPECTED_RE_TYPE: typing.Sequence\[builtins.str\*?\] + # EXPECTED_RE_TYPE: typing.Sequence\[str\*?\] reveal_type(data) async def t_async_connection_execute_multi() -> None: result = (await async_connection.execute(multi_stmt)).t - # EXPECTED_RE_TYPE: sqlalchemy.*TupleResult\[Tuple\[builtins.int\*?, builtins.str\*?\]\] + # EXPECTED_RE_TYPE: sqlalchemy.*TupleResult\[Tuple\[int\*?, str\*?\]\] reveal_type(result) row = result.one() - # EXPECTED_RE_TYPE: Tuple\[builtins.int\*?, builtins.str\*?\] + # EXPECTED_RE_TYPE: Tuple\[int\*?, str\*?\] reveal_type(row) x, y = row - # EXPECTED_RE_TYPE: builtins.int\*? + # EXPECTED_RE_TYPE: int\*? reveal_type(x) - # EXPECTED_RE_TYPE: builtins.str\*? + # EXPECTED_RE_TYPE: str\*? reveal_type(y) async def t_async_connection_execute_single() -> None: result = (await async_connection.execute(single_stmt)).t - # EXPECTED_RE_TYPE: sqlalchemy.*TupleResult\[Tuple\[builtins.str\*?\]\] + # EXPECTED_RE_TYPE: sqlalchemy.*TupleResult\[Tuple\[str\*?\]\] reveal_type(result) row = result.one() - # EXPECTED_RE_TYPE: Tuple\[builtins.str\*?\] + # EXPECTED_RE_TYPE: Tuple\[str\*?\] reveal_type(row) (x,) = row - # EXPECTED_RE_TYPE: builtins.str\*? + # EXPECTED_RE_TYPE: str\*? reveal_type(x) async def t_async_connection_scalar() -> None: obj = await async_connection.scalar(single_stmt) - # EXPECTED_RE_TYPE: builtins.str \| None + # EXPECTED_RE_TYPE: str \| None reveal_type(obj) async def t_async_connection_scalars() -> None: result = await async_connection.scalars(single_stmt) - # EXPECTED_RE_TYPE: sqlalchemy.*ScalarResult\*?\[builtins.str\*?\] + # EXPECTED_RE_TYPE: sqlalchemy.*ScalarResult\*?\[str\*?\] reveal_type(result) data = result.all() - # EXPECTED_RE_TYPE: typing.Sequence\[builtins.str\*?\] + # EXPECTED_RE_TYPE: typing.Sequence\[str\*?\] reveal_type(data) async def t_async_session_execute_multi() -> None: result = (await async_session.execute(multi_stmt)).t - # EXPECTED_RE_TYPE: sqlalchemy.*TupleResult\[Tuple\[builtins.int\*?, builtins.str\*?\]\] + # EXPECTED_RE_TYPE: sqlalchemy.*TupleResult\[Tuple\[int\*?, str\*?\]\] reveal_type(result) row = result.one() - # EXPECTED_RE_TYPE: Tuple\[builtins.int\*?, builtins.str\*?\] + # EXPECTED_RE_TYPE: Tuple\[int\*?, str\*?\] reveal_type(row) x, y = row - # EXPECTED_RE_TYPE: builtins.int\*? + # EXPECTED_RE_TYPE: int\*? reveal_type(x) - # EXPECTED_RE_TYPE: builtins.str\*? + # EXPECTED_RE_TYPE: str\*? reveal_type(y) async def t_async_session_execute_single() -> None: result = (await async_session.execute(single_stmt)).t - # EXPECTED_RE_TYPE: sqlalchemy.*TupleResult\[Tuple\[builtins.str\*?\]\] + # EXPECTED_RE_TYPE: sqlalchemy.*TupleResult\[Tuple\[str\*?\]\] reveal_type(result) row = result.one() - # EXPECTED_RE_TYPE: Tuple\[builtins.str\*?\] + # EXPECTED_RE_TYPE: Tuple\[str\*?\] reveal_type(row) (x,) = row - # EXPECTED_RE_TYPE: builtins.str\*? + # EXPECTED_RE_TYPE: str\*? reveal_type(x) async def t_async_session_scalar() -> None: obj = await async_session.scalar(single_stmt) - # EXPECTED_RE_TYPE: builtins.str \| None + # EXPECTED_RE_TYPE: str \| None reveal_type(obj) async def t_async_session_scalars() -> None: result = await async_session.scalars(single_stmt) - # EXPECTED_RE_TYPE: sqlalchemy.*ScalarResult\*?\[builtins.str\*?\] + # EXPECTED_RE_TYPE: sqlalchemy.*ScalarResult\*?\[str\*?\] reveal_type(result) data = result.all() - # EXPECTED_RE_TYPE: typing.Sequence\[builtins.str\*?\] + # EXPECTED_RE_TYPE: typing.Sequence\[str\*?\] reveal_type(data) async def t_async_connection_stream_multi() -> None: result = (await async_connection.stream(multi_stmt)).t - # EXPECTED_RE_TYPE: sqlalchemy.*AsyncTupleResult\[Tuple\[builtins.int\*?, builtins.str\*?\]\] + # EXPECTED_RE_TYPE: sqlalchemy.*AsyncTupleResult\[Tuple\[int\*?, str\*?\]\] reveal_type(result) row = await result.one() - # EXPECTED_RE_TYPE: Tuple\[builtins.int\*?, builtins.str\*?\] + # EXPECTED_RE_TYPE: Tuple\[int\*?, str\*?\] reveal_type(row) x, y = row - # EXPECTED_RE_TYPE: builtins.int\*? + # EXPECTED_RE_TYPE: int\*? reveal_type(x) - # EXPECTED_RE_TYPE: builtins.str\*? + # EXPECTED_RE_TYPE: str\*? reveal_type(y) async def t_async_connection_stream_single() -> None: result = (await async_connection.stream(single_stmt)).t - # EXPECTED_RE_TYPE: sqlalchemy.*AsyncTupleResult\[Tuple\[builtins.str\*?\]\] + # EXPECTED_RE_TYPE: sqlalchemy.*AsyncTupleResult\[Tuple\[str\*?\]\] reveal_type(result) row = await result.one() - # EXPECTED_RE_TYPE: Tuple\[builtins.str\*?\] + # EXPECTED_RE_TYPE: Tuple\[str\*?\] reveal_type(row) (x,) = row - # EXPECTED_RE_TYPE: builtins.str\*? + # EXPECTED_RE_TYPE: str\*? reveal_type(x) async def t_async_connection_stream_scalars() -> None: result = await async_connection.stream_scalars(single_stmt) - # EXPECTED_RE_TYPE: sqlalchemy.*AsyncScalarResult\*?\[builtins.str\*?\] + # EXPECTED_RE_TYPE: sqlalchemy.*AsyncScalarResult\*?\[str\*?\] reveal_type(result) data = await result.all() - # EXPECTED_RE_TYPE: typing.Sequence\*?\[builtins.str\*?\] + # EXPECTED_RE_TYPE: typing.Sequence\*?\[str\*?\] reveal_type(data) async def t_async_session_stream_multi() -> None: result = (await async_session.stream(multi_stmt)).t - # EXPECTED_RE_TYPE: sqlalchemy.*TupleResult\[Tuple\[builtins.int\*?, builtins.str\*?\]\] + # EXPECTED_RE_TYPE: sqlalchemy.*TupleResult\[Tuple\[int\*?, str\*?\]\] reveal_type(result) row = await result.one() - # EXPECTED_RE_TYPE: Tuple\[builtins.int\*?, builtins.str\*?\] + # EXPECTED_RE_TYPE: Tuple\[int\*?, str\*?\] reveal_type(row) x, y = row - # EXPECTED_RE_TYPE: builtins.int\*? + # EXPECTED_RE_TYPE: int\*? reveal_type(x) - # EXPECTED_RE_TYPE: builtins.str\*? + # EXPECTED_RE_TYPE: str\*? reveal_type(y) async def t_async_session_stream_single() -> None: result = (await async_session.stream(single_stmt)).t - # EXPECTED_RE_TYPE: sqlalchemy.*AsyncTupleResult\[Tuple\[builtins.str\*?\]\] + # EXPECTED_RE_TYPE: sqlalchemy.*AsyncTupleResult\[Tuple\[str\*?\]\] reveal_type(result) row = await result.one() - # EXPECTED_RE_TYPE: Tuple\[builtins.str\*?\] + # EXPECTED_RE_TYPE: Tuple\[str\*?\] reveal_type(row) (x,) = row - # EXPECTED_RE_TYPE: builtins.str\*? + # EXPECTED_RE_TYPE: str\*? reveal_type(x) async def t_async_session_stream_scalars() -> None: result = await async_session.stream_scalars(single_stmt) - # EXPECTED_RE_TYPE: sqlalchemy.*AsyncScalarResult\*?\[builtins.str\*?\] + # EXPECTED_RE_TYPE: sqlalchemy.*AsyncScalarResult\*?\[str\*?\] reveal_type(result) data = await result.all() - # EXPECTED_RE_TYPE: typing.Sequence\*?\[builtins.str\*?\] + # EXPECTED_RE_TYPE: typing.Sequence\*?\[str\*?\] reveal_type(data)