Skip to content

Commit 706fbe8

Browse files
Preserve parens when merging type: ignore with other comments to prevent AST errors
1 parent 5b470f0 commit 706fbe8

File tree

3 files changed

+47
-0
lines changed

3 files changed

+47
-0
lines changed

CHANGES.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
- Fix crash when multiple `# fmt: skip` comments are used in a multi-part if-clause, on
2121
string literals, or on dictionary entries with long lines (#4872)
2222
- Fix possible crash when `fmt: ` directives aren't on the top level (#4856)
23+
- Preserve parentheses when `# type: ignore` comments would be merged with other
24+
comments on the same line, preventing AST equivalence failures (#4880)
2325

2426
### Preview style
2527

src/black/lines.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -974,6 +974,24 @@ def can_omit_invisible_parens(
974974
"""
975975
line = rhs.body
976976

977+
# We can't omit parens if doing so would result in a type: ignore comment
978+
# sharing a line with other comments, as that breaks type: ignore parsing.
979+
# Check if there's a type: ignore comment in any part
980+
has_type_ignore_comment = False
981+
has_other_comment = False
982+
983+
for part in (rhs.head, rhs.body, rhs.tail):
984+
for leaf in part.leaves:
985+
for comment in part.comments.get(id(leaf), []):
986+
if is_type_ignore_comment(comment, mode=part.mode):
987+
has_type_ignore_comment = True
988+
else:
989+
has_other_comment = True
990+
991+
# If there's both a type: ignore comment and other comments, keep the parens
992+
if has_type_ignore_comment and has_other_comment:
993+
return False
994+
977995
# We need optional parens in order to split standalone comments to their own lines
978996
# if there are no nested parens around the standalone comments
979997
closing_bracket: Leaf | None = None
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import pandas as pd
2+
3+
interval_td = pd.Interval(
4+
pd.Timedelta("1 days"), pd.Timedelta("2 days"), closed="neither"
5+
)
6+
7+
_td = ( # pyright: ignore[reportOperatorIssue,reportUnknownVariableType]
8+
interval_td
9+
- pd.Interval( # type: ignore[operator]
10+
pd.Timedelta(1, "ns"), pd.Timedelta(2, "ns")
11+
)
12+
)
13+
14+
# output
15+
16+
import pandas as pd
17+
18+
interval_td = pd.Interval(
19+
pd.Timedelta("1 days"), pd.Timedelta("2 days"), closed="neither"
20+
)
21+
22+
_td = ( # pyright: ignore[reportOperatorIssue,reportUnknownVariableType]
23+
interval_td
24+
- pd.Interval( # type: ignore[operator]
25+
pd.Timedelta(1, "ns"), pd.Timedelta(2, "ns")
26+
)
27+
)

0 commit comments

Comments
 (0)