Skip to content

Commit 3edeef0

Browse files
[primer] Separate false positive sections in primer comment
New useless-suppression messages get a πŸŽ‰ section (fixed FP), and new locally-disabled messages get a 😞 section (introduced FP).
1 parent e16ee02 commit 3edeef0

4 files changed

Lines changed: 98 additions & 46 deletions

File tree

β€Žpylint/testutils/_primer/primer_compare_command.pyβ€Ž

Lines changed: 86 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
# Copyright (c) https://github.com/pylint-dev/pylint/blob/main/CONTRIBUTORS.txt
44
from __future__ import annotations
55

6+
import re
7+
from collections.abc import Callable
68
from pathlib import PurePosixPath
79

810
from pylint.reporters.json_reporter import OldJsonExport
@@ -14,6 +16,66 @@
1416
from pylint.testutils._primer.primer_command import PrimerCommand
1517

1618
MAX_GITHUB_COMMENT_LENGTH = 65536
19+
USELESS_SUPPRESSION_RE = re.compile(r"Useless suppression of '(.+)'")
20+
21+
22+
class _ClassifiedMessages:
23+
"""All message categories for a single package, pre-formatted for display."""
24+
25+
__slots__ = (
26+
"astroid_errors",
27+
"changed_messages",
28+
"fixed_false_positives",
29+
"missing_messages",
30+
"new_false_positives",
31+
"new_messages",
32+
)
33+
34+
def __init__(
35+
self,
36+
new_messages: list[OldJsonExport],
37+
missing_messages: list[OldJsonExport],
38+
changed_messages: list[ChangedMessage],
39+
source_link: Callable[[OldJsonExport], str],
40+
) -> None:
41+
astroid_errors = 0
42+
new_fp: list[OldJsonExport] = []
43+
fixed_fp: list[OldJsonExport] = []
44+
other_new: list[OldJsonExport] = []
45+
for message in new_messages:
46+
if message["symbol"] == "astroid-error":
47+
astroid_errors += 1
48+
elif USELESS_SUPPRESSION_RE.match(message["message"]):
49+
fixed_fp.append(message)
50+
elif message["symbol"] == "locally-disabled":
51+
# A new locally-disabled means a maintainer had to add a
52+
# suppression comment β€” we introduced a false positive.
53+
new_fp.append(message)
54+
else:
55+
other_new.append(message)
56+
57+
def _format(msgs: list[OldJsonExport]) -> str:
58+
body = ""
59+
for count, msg in enumerate(msgs, 1):
60+
body += (
61+
f"{count}) {msg['symbol']}:\n*{msg['message']}*\n"
62+
f"{source_link(msg)}\n"
63+
)
64+
return body
65+
66+
self.astroid_errors = astroid_errors
67+
self.fixed_false_positives = _format(fixed_fp)
68+
self.new_false_positives = _format(new_fp)
69+
self.new_messages = _format(other_new)
70+
self.missing_messages = _format(missing_messages)
71+
72+
body = ""
73+
for count, (old, new) in enumerate(changed_messages, 1):
74+
body += (
75+
f"{count}) [{new['symbol']}]({source_link(new)}):\n"
76+
f"{message_diff(old, new)}\n"
77+
)
78+
self.changed_messages = body
1779

1880

1981
class CompareCommand(PrimerCommand):
@@ -70,58 +132,41 @@ def _details_section(title: str, body: str) -> str:
70132
# Two line breaks required after <details> for links to work.
71133
return f"{title}\n\n<details>\n\n{body}</details>\n\n"
72134

135+
classified = _ClassifiedMessages(
136+
new_messages, missing_messages, changed_messages, _source_link
137+
)
73138
comment = f"\n**Effect on [{package}]({url}):**\n\n"
74139

75-
# -- Changed messages (same diagnostic, different details) -----------
76-
if changed_messages:
77-
body = ""
78-
for count, (old, new) in enumerate(changed_messages, 1):
79-
body += (
80-
f"{count}) [{new['symbol']}]({_source_link(new)}):\n"
81-
f"{message_diff(old, new)}\n"
82-
)
140+
if classified.changed_messages:
83141
comment += _details_section(
84-
"The following messages have been changed:", body
142+
"The following messages have been changed:",
143+
classified.changed_messages,
85144
)
86-
87-
# -- New messages ----------------------------------------------------
88-
astroid_errors = 0
89-
new_non_astroid_messages = ""
90-
count = 0
91-
for message in new_messages:
92-
# Existing astroid errors may still show up as "new" because the
93-
# timestamp in the message is slightly different.
94-
if message["symbol"] == "astroid-error":
95-
astroid_errors += 1
96-
else:
97-
count += 1
98-
new_non_astroid_messages += (
99-
f"{count}) {message['symbol']}:\n*{message['message']}*\n"
100-
f"{_source_link(message)}\n"
101-
)
102-
103-
if astroid_errors:
145+
if classified.astroid_errors:
104146
comment += (
105-
f'{astroid_errors} "astroid error(s)" were found. '
147+
f'{classified.astroid_errors} "astroid error(s)" were found. '
106148
"Please open the GitHub Actions log to see what failed or crashed.\n\n"
107149
)
108-
if new_non_astroid_messages:
150+
if classified.fixed_false_positives:
109151
comment += _details_section(
110-
"The following messages are now emitted:", new_non_astroid_messages
152+
"πŸŽ‰ The following false positives have been fixed:",
153+
classified.fixed_false_positives,
111154
)
112-
113-
# -- Missing messages ------------------------------------------------
114-
if missing_messages:
115-
body = ""
116-
for count, message in enumerate(missing_messages, 1):
117-
body += (
118-
f"{count}) {message['symbol']}:\n*{message['message']}*\n"
119-
f"{_source_link(message)}\n"
120-
)
155+
if classified.new_false_positives:
121156
comment += _details_section(
122-
"The following messages are no longer emitted:", body
157+
"😞 The following false positives have been introduced:",
158+
classified.new_false_positives,
159+
)
160+
if classified.new_messages:
161+
comment += _details_section(
162+
"The following messages are now emitted:",
163+
classified.new_messages,
164+
)
165+
if classified.missing_messages:
166+
comment += _details_section(
167+
"The following messages are no longer emitted:",
168+
classified.missing_messages,
123169
)
124-
125170
return comment
126171

127172
def _truncate_comment(self, comment: str) -> str:

β€Žtests/testutils/_primer/cases/batched/expected.txtβ€Ž

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
The following messages are no longer emitted:
77

88
<details>
9+
910
1) locally-disabled:
1011
*Locally disabling redefined-builtin (W0622)*
1112
https://github.com/pylint-dev/astroid/blob/1234567890abcdef/astroid/__init__.py#L91

β€Žtests/testutils/_primer/cases/new_message/expected.txtβ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
**Effect on [astroid](https://github.com/pylint-dev/astroid):**
55

6-
The following messages are now emitted:
6+
😞 The following false positives have been introduced:
77

88
<details>
99

β€Žtests/testutils/_primer/cases/useless_suppression/expected.txtβ€Ž

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,22 @@
33

44
**Effect on [astropy](https://github.com/astropy/astropy):**
55

6-
The following messages are now emitted:
6+
πŸŽ‰ The following false positives have been fixed:
7+
8+
<details>
9+
10+
1) useless-suppression:
11+
*Useless suppression of 'looping-through-iterator'*
12+
https://github.com/astropy/astropy/blob/1fb40bc1f22f176254ef583065aa155f53f3b414/astropy/coordinates/angles/angle_parsetab.py#L14
13+
</details>
14+
15+
😞 The following false positives have been introduced:
716

817
<details>
918

1019
1) locally-disabled:
1120
*Locally disabling looping-through-iterator (W4801)*
1221
https://github.com/astropy/astropy/blob/1fb40bc1f22f176254ef583065aa155f53f3b414/astropy/coordinates/angles/angle_parsetab.py#L14
13-
2) useless-suppression:
14-
*Useless suppression of 'looping-through-iterator'*
15-
https://github.com/astropy/astropy/blob/1fb40bc1f22f176254ef583065aa155f53f3b414/astropy/coordinates/angles/angle_parsetab.py#L14
1622
</details>
1723

1824
*This comment was generated for commit v2.14.2*

0 commit comments

Comments
Β (0)