File tree 4 files changed +65
-0
lines changed
4 files changed +65
-0
lines changed Original file line number Diff line number Diff line change 15
15
- Handle ` # fmt: skip ` followed by a comment at the end of file (#4635 )
16
16
- Fix crash when a tuple appears in the ` as ` clause of a ` with ` statement
17
17
(#4634 )
18
+ - Fix crash when tuple is used as a context manager inside a ` with ` statement (#4646 )
18
19
19
20
### Preview style
20
21
Original file line number Diff line number Diff line change 40
40
ensure_visible ,
41
41
fstring_to_string ,
42
42
get_annotation_type ,
43
+ has_sibling_with_type ,
43
44
is_arith_like ,
44
45
is_async_stmt_or_funcdef ,
45
46
is_atom_with_invisible_parens ,
@@ -1628,6 +1629,11 @@ def maybe_make_parens_invisible_in_atom(
1628
1629
or is_empty_tuple (node )
1629
1630
or is_one_tuple (node )
1630
1631
or (is_tuple (node ) and parent .type == syms .asexpr_test )
1632
+ or (
1633
+ is_tuple (node )
1634
+ and parent .type == syms .with_stmt
1635
+ and has_sibling_with_type (node , token .COMMA )
1636
+ )
1631
1637
or (is_yield (node ) and parent .type != syms .expr_stmt )
1632
1638
or (
1633
1639
# This condition tries to prevent removing non-optional brackets
Original file line number Diff line number Diff line change @@ -1058,3 +1058,21 @@ def furthest_ancestor_with_last_leaf(leaf: Leaf) -> LN:
1058
1058
while node .parent and node .parent .children and node is node .parent .children [- 1 ]:
1059
1059
node = node .parent
1060
1060
return node
1061
+
1062
+
1063
+ def has_sibling_with_type (node : LN , type : int ) -> bool :
1064
+ # Check previous siblings
1065
+ sibling = node .prev_sibling
1066
+ while sibling is not None :
1067
+ if sibling .type == type :
1068
+ return True
1069
+ sibling = sibling .prev_sibling
1070
+
1071
+ # Check next siblings
1072
+ sibling = node .next_sibling
1073
+ while sibling is not None :
1074
+ if sibling .type == type :
1075
+ return True
1076
+ sibling = sibling .next_sibling
1077
+
1078
+ return False
Original file line number Diff line number Diff line change @@ -89,6 +89,26 @@ async def func():
89
89
with (x , y ) as z :
90
90
pass
91
91
92
+
93
+ # don't remove the brackets here, it changes the meaning of the code.
94
+ # even though the code will always trigger a runtime error
95
+ with (name_5 , name_4 ), name_5 :
96
+ pass
97
+
98
+
99
+ def test_tuple_as_contextmanager ():
100
+ from contextlib import nullcontext
101
+
102
+ try :
103
+ with (nullcontext (),nullcontext ()),nullcontext ():
104
+ pass
105
+ except TypeError :
106
+ # test passed
107
+ pass
108
+ else :
109
+ # this should be a type error
110
+ assert False
111
+
92
112
# output
93
113
94
114
@@ -182,3 +202,23 @@ async def func():
182
202
# don't remove the brackets here, it changes the meaning of the code.
183
203
with (x , y ) as z :
184
204
pass
205
+
206
+
207
+ # don't remove the brackets here, it changes the meaning of the code.
208
+ # even though the code will always trigger a runtime error
209
+ with (name_5 , name_4 ), name_5 :
210
+ pass
211
+
212
+
213
+ def test_tuple_as_contextmanager ():
214
+ from contextlib import nullcontext
215
+
216
+ try :
217
+ with (nullcontext (), nullcontext ()), nullcontext ():
218
+ pass
219
+ except TypeError :
220
+ # test passed
221
+ pass
222
+ else :
223
+ # this should be a type error
224
+ assert False
You can’t perform that action at this time.
0 commit comments