Skip to content

Commit c748ba3

Browse files
authored
Type relationship as list (#154)
Currently, the plugin types relationships with uselist as Iterable[X], but these relationships actually expose a list with list semantics, including .append(), assignments, etc. This PR updates the plugin to type those relationships with List[X] instead of Iterable[X]. Ref: https://docs.sqlalchemy.org/en/13/orm/relationship_api.html#sqlalchemy.orm.relationship.params.uselist Ref of usage with assignment: https://docs.sqlalchemy.org/en/13/orm/tutorial.html#working-with-related-objects Ref of usage with append: https://docs.sqlalchemy.org/en/13/orm/tutorial.html#building-a-many-to-many-relationship Note: I'm by no means expert in mypy internals and its plugins, I'm not 100% sure the usage of ctx.api.named_generic_type('builtins.list', [new_arg]) is correct here, but I see that seems to be how it's used by mypy: https://github.com/python/mypy/blob/master/mypy/plugins/ctypes.py#L158
1 parent 027e0e9 commit c748ba3

File tree

2 files changed

+7
-9
lines changed

2 files changed

+7
-9
lines changed

sqlmypy.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -396,10 +396,10 @@ class User(Base):
396396
# Something complex, stay silent for now.
397397
new_arg = AnyType(TypeOfAny.special_form)
398398

399-
# We figured out, the model type. Now check if we need to wrap it in Iterable
399+
# We figured out, the model type. Now check if we need to wrap it in List
400400
if uselist_arg:
401401
if parse_bool(uselist_arg):
402-
new_arg = ctx.api.named_generic_type('typing.Iterable', [new_arg])
402+
new_arg = ctx.api.named_generic_type('builtins.list', [new_arg])
403403
else:
404404
if has_annotation:
405405
# If there is an annotation we use it as a source of truth.

test/test-data/sqlalchemy-plugin-features.test

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,6 @@ Base = declarative_base()
131131
from sqlalchemy.ext.declarative import declarative_base
132132
from sqlalchemy import Column, Integer, String
133133
from sqlalchemy.orm import relationship, RelationshipProperty
134-
from typing import Iterable
135134

136135
Base = declarative_base()
137136

@@ -144,7 +143,7 @@ class User(Base):
144143

145144
user = User()
146145
reveal_type(user.first_other) # N: Revealed type is 'main.Other*'
147-
reveal_type(user.second_other) # N: Revealed type is 'typing.Iterable*[main.Other]'
146+
reveal_type(user.second_other) # N: Revealed type is 'builtins.list*[main.Other]'
148147

149148
class Other(Base):
150149
__tablename__ = 'other'
@@ -155,7 +154,6 @@ class Other(Base):
155154
from sqlalchemy.ext.declarative import declarative_base
156155
from sqlalchemy import Column, Integer, String
157156
from sqlalchemy.orm import relationship, RelationshipProperty
158-
from typing import Iterable
159157

160158
Base = declarative_base()
161159

@@ -169,7 +167,7 @@ class User(Base):
169167

170168
user = User()
171169
reveal_type(user.first_other) # N: Revealed type is 'main.Other*'
172-
reveal_type(user.second_other) # N: Revealed type is 'typing.Iterable*[main.Other]'
170+
reveal_type(user.second_other) # N: Revealed type is 'builtins.list*[main.Other]'
173171

174172
class Other(Base):
175173
__tablename__ = 'other'
@@ -180,17 +178,17 @@ class Other(Base):
180178
from sqlalchemy.ext.declarative import declarative_base
181179
from sqlalchemy import Column, Integer, String
182180
from sqlalchemy.orm import relationship, RelationshipProperty
183-
from typing import Iterable
181+
from typing import List
184182

185183
Base = declarative_base()
186184

187185
class User(Base):
188186
__tablename__ = 'users'
189187
id = Column(Integer(), primary_key=True)
190188
first_other: RelationshipProperty[Other] = relationship('Other')
191-
second_other: RelationshipProperty[Iterable[Other]] = relationship(Other, uselist=True)
189+
second_other: RelationshipProperty[List[Other]] = relationship(Other, uselist=True)
192190
third_other: RelationshipProperty[Other] = relationship(Other, uselist=False)
193-
bad_other: RelationshipProperty[Other] = relationship('Other', uselist=True) # E: Incompatible types in assignment (expression has type "RelationshipProperty[Iterable[Other]]", variable has type "RelationshipProperty[Other]")
191+
bad_other: RelationshipProperty[Other] = relationship('Other', uselist=True) # E: Incompatible types in assignment (expression has type "RelationshipProperty[List[Other]]", variable has type "RelationshipProperty[Other]")
194192

195193
class Other(Base):
196194
__tablename__ = 'other'

0 commit comments

Comments
 (0)