Skip to content

Commit 41f0d20

Browse files
authored
Type stubs for indexing into a ListAttribute in conditional expressions (#774)
1 parent 20032fa commit 41f0d20

File tree

5 files changed

+36
-4
lines changed

5 files changed

+36
-4
lines changed

docs/release_notes.rst

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,19 @@
11
Release Notes
22
=============
33

4+
v4.3.3
5+
----------
6+
7+
* Add type stubs for indexing into a ``ListAttribute`` for forming conditional expressions (#774)
8+
9+
::
10+
11+
class MyModel(Model):
12+
...
13+
my_list = ListAttribute()
14+
15+
MyModel.query(..., condition=MyModel.my_list[0] == 42)
16+
417
v4.3.2
518
----------
619

pynamodb/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,4 @@
77
"""
88
__author__ = 'Jharrod LaFon'
99
__license__ = 'MIT'
10-
__version__ = '4.3.2'
10+
__version__ = '4.3.3'

pynamodb/attributes.pyi

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ from pynamodb.expressions.condition import (
66
BeginsWith, Between, Comparison, Contains, NotExists, Exists, In
77
)
88
from pynamodb.expressions.operand import (
9-
_Decrement, _IfNotExists, _Increment, _ListAppend
9+
Path, _Decrement, _IfNotExists, _Increment, _ListAppend
1010
)
1111
from pynamodb.expressions.update import (
1212
AddAction, DeleteAction, RemoveAction, SetAction, ListRemoveAction
@@ -168,6 +168,7 @@ class ListAttribute(Generic[_T], Attribute[List[_T]]):
168168
def __get__(self: _A, instance: None, owner: Any) -> _A: ...
169169
@overload
170170
def __get__(self, instance: Any, owner: Any) -> List[_T]: ...
171+
def __getitem__(self, idx: int) -> Path: ...
171172
def remove_indexes(self, *indexes: int) -> Union[ListRemoveAction]: ...
172173

173174

pynamodb/expressions/operand.pyi

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,3 +79,4 @@ class Path(_NumericOperand, _ListAppendOperand, _ConditionOperand):
7979
def set(self, value: Any) -> SetAction: ...
8080
def remove(self) -> RemoveAction: ...
8181
def remove_list_elements(self, *indexes: int) -> ListRemoveAction: ...
82+
def __getitem__(self, idx: Union[int, str]) -> Path: ...

tests/test_mypy.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,15 +142,32 @@ class MyModel(Model):
142142
143143
reveal_type(MyModel.my_list) # E: Revealed type is 'pynamodb.attributes.ListAttribute[__main__.MyMap]'
144144
reveal_type(MyModel().my_list) # E: Revealed type is 'builtins.list[__main__.MyMap*]'
145-
reveal_type(MyModel.my_list[0]) # E: Value of type "ListAttribute[MyMap]" is not indexable # E: Revealed type is 'Any'
146145
reveal_type(MyModel().my_list[0].my_sub_attr) # E: Revealed type is 'builtins.str'
147146
148147
# Untyped lists are not well supported yet
149-
reveal_type(MyModel.my_untyped_list[0]) # E: Value of type "ListAttribute[Any]" is not indexable # E: Revealed type is 'Any'
150148
reveal_type(MyModel().my_untyped_list[0].my_sub_attr) # E: Revealed type is 'Any'
151149
""")
152150

153151

152+
def test_paths():
153+
assert_mypy_output("""
154+
from pynamodb.attributes import ListAttribute, MapAttribute, UnicodeAttribute
155+
from pynamodb.models import Model
156+
157+
class MyMap(MapAttribute):
158+
my_sub_attr = UnicodeAttribute()
159+
160+
class MyModel(Model):
161+
my_list = ListAttribute(of=MyMap)
162+
my_map = MyMap()
163+
164+
reveal_type(MyModel.my_list[0]) # E: Revealed type is 'pynamodb.expressions.operand.Path'
165+
reveal_type(MyModel.my_list[0] == MyModel()) # E: Revealed type is 'pynamodb.expressions.condition.Comparison'
166+
# the following string indexing is not type checked - not by mypy nor in runtime
167+
reveal_type(MyModel.my_list[0]['my_sub_attr'] == 'foobar') # E: Revealed type is 'pynamodb.expressions.condition.Comparison'
168+
""")
169+
170+
154171
def test_index_query_scan():
155172
assert_mypy_output("""
156173
from pynamodb.attributes import NumberAttribute

0 commit comments

Comments
 (0)