honor dict key / value iteration order (#872)
diff --git a/pyflakes/checker.py b/pyflakes/checker.py
index 5dc3251..4c05298 100644
--- a/pyflakes/checker.py
+++ b/pyflakes/checker.py
@@ -16,6 +16,7 @@
import string
import sys
import warnings
+from collections.abc import Iterable
from pyflakes import messages
@@ -169,6 +170,10 @@
yield item
+def iter_dict_children(node: ast.Dict) -> Iterable[tuple[ast.AST, ast.AST]]:
+ return zip(node.keys, node.values)
+
+
def convert_to_value(item):
if isinstance(item, ast.Constant):
return item.value
@@ -1607,8 +1612,9 @@
# TypedDict("a", {"a": int})
if len(node.args) > 1 and isinstance(node.args[1], ast.Dict):
- _non_annotations(node.args[1].keys)
- _annotations(node.args[1].values)
+ for k, v in iter_dict_children(node.args[1]):
+ _non_annotation(k)
+ _annotation(v)
_non_annotations(node.args[2:])
# TypedDict("a", a=int)
@@ -1861,7 +1867,10 @@
key_node,
key,
)
- self.handleChildren(node)
+
+ for k, v in iter_dict_children(node):
+ self.handleNode(k, node)
+ self.handleNode(v, node)
def IF(self, node):
if isinstance(node.test, ast.Tuple) and node.test.elts != []:
diff --git a/pyflakes/test/test_other.py b/pyflakes/test/test_other.py
index 77f7606..9c6c5ba 100644
--- a/pyflakes/test/test_other.py
+++ b/pyflakes/test/test_other.py
@@ -1810,6 +1810,15 @@
print(z)
''')
+ def test_dict_key_value_ordering_assignment_expressions(self):
+ # https://docs.python.org/3/reference/expressions.html#dictionary-displays
+ self.flakes('''
+ {
+ '1': (y := 2),
+ y: '3',
+ }
+ ''')
+
@skipIf(version_info < (3, 15), 'new in Python 3.15')
def test_reassigned_in_comprehension_unpacking(self):
self.flakes('''
diff --git a/pyflakes/test/test_type_annotations.py b/pyflakes/test/test_type_annotations.py
index b86bdca..4416a2a 100644
--- a/pyflakes/test/test_type_annotations.py
+++ b/pyflakes/test/test_type_annotations.py
@@ -788,6 +788,13 @@
TypedDict("U", x="T")
''')
+ def test_typeddict_key_value_ordering(self):
+ self.flakes("""
+ from typing import TypedDict
+ from u import V
+ TypedDict("TD", {"k": (y := "V"), y: "V"})
+ """)
+
def test_namedtypes_classes(self):
self.flakes("""
from typing import TypedDict, NamedTuple