Skip to content

Commit b047220

Browse files
DanielNoordPierre-Sassoulas
authored andcommitted
Make disable-next only consider the succeeding line (#7411)
1 parent fb3a641 commit b047220

File tree

6 files changed

+54
-22
lines changed

6 files changed

+54
-22
lines changed

doc/whatsnew/fragments/7401.bugfix

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
``disable-next`` is now correctly scoped to only the succeeding line.
2+
3+
Closes #7401

pylint/checkers/variables.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -2209,9 +2209,8 @@ def _loopvar_name(self, node: astroid.Name) -> None:
22092209
# scope lookup rules would need to be changed to return the initial
22102210
# assignment (which does not exist in code per se) as well as any later
22112211
# modifications.
2212-
# pylint: disable-next=too-many-boolean-expressions
22132212
if (
2214-
not astmts
2213+
not astmts # pylint: disable=too-many-boolean-expressions
22152214
or (
22162215
astmts[0].parent == astmts[0].root()
22172216
and astmts[0].parent.parent_of(node)

pylint/lint/message_state_handler.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,10 @@ def _set_one_msg_status(
7070
self, scope: str, msg: MessageDefinition, line: int | None, enable: bool
7171
) -> None:
7272
"""Set the status of an individual message."""
73-
if scope == "module":
73+
if scope in {"module", "line"}:
7474
assert isinstance(line, int) # should always be int inside module scope
7575

76-
self.linter.file_state.set_msg_status(msg, line, enable)
76+
self.linter.file_state.set_msg_status(msg, line, enable, scope)
7777
if not enable and msg.symbol != "locally-disabled":
7878
self.linter.add_message(
7979
"locally-disabled", line=line, args=(msg.symbol, msg.msgid)
@@ -143,7 +143,7 @@ def _set_msg_status(
143143
ignore_unknown: bool = False,
144144
) -> None:
145145
"""Do some tests and then iterate over message definitions to set state."""
146-
assert scope in {"package", "module"}
146+
assert scope in {"package", "module", "line"}
147147

148148
message_definitions = self._get_messages_to_set(msgid, enable, ignore_unknown)
149149

@@ -197,7 +197,7 @@ def disable(
197197
def disable_next(
198198
self,
199199
msgid: str,
200-
scope: str = "package",
200+
_: str = "package",
201201
line: int | None = None,
202202
ignore_unknown: bool = False,
203203
) -> None:
@@ -207,7 +207,7 @@ def disable_next(
207207
self._set_msg_status(
208208
msgid,
209209
enable=False,
210-
scope=scope,
210+
scope="line",
211211
line=line + 1,
212212
ignore_unknown=ignore_unknown,
213213
)

pylint/utils/file_state.py

+35-15
Original file line numberDiff line numberDiff line change
@@ -194,30 +194,50 @@ def _set_message_state_in_block(
194194
state = lines[line]
195195
original_lineno = line
196196

197-
# Update suppression mapping
198-
if not state:
199-
self._suppression_mapping[(msg.msgid, line)] = original_lineno
200-
else:
201-
self._suppression_mapping.pop((msg.msgid, line), None)
197+
self._set_message_state_on_line(msg, line, state, original_lineno)
202198

203-
# Update message state for respective line
204-
try:
205-
self._module_msgs_state[msg.msgid][line] = state
206-
except KeyError:
207-
self._module_msgs_state[msg.msgid] = {line: state}
208199
del lines[lineno]
209200

210-
def set_msg_status(self, msg: MessageDefinition, line: int, status: bool) -> None:
201+
def _set_message_state_on_line(
202+
self,
203+
msg: MessageDefinition,
204+
line: int,
205+
state: bool,
206+
original_lineno: int,
207+
) -> None:
208+
"""Set the state of a message on a line."""
209+
# Update suppression mapping
210+
if not state:
211+
self._suppression_mapping[(msg.msgid, line)] = original_lineno
212+
else:
213+
self._suppression_mapping.pop((msg.msgid, line), None)
214+
215+
# Update message state for respective line
216+
try:
217+
self._module_msgs_state[msg.msgid][line] = state
218+
except KeyError:
219+
self._module_msgs_state[msg.msgid] = {line: state}
220+
221+
def set_msg_status(
222+
self,
223+
msg: MessageDefinition,
224+
line: int,
225+
status: bool,
226+
scope: str = "package",
227+
) -> None:
211228
"""Set status (enabled/disable) for a given message at a given line."""
212229
assert line > 0
213230
assert self._module
214231
# TODO: 3.0: Remove unnecessary assertion
215232
assert self._msgs_store
216233

217-
# Expand the status to cover all relevant block lines
218-
self._set_state_on_block_lines(
219-
self._msgs_store, self._module, msg, {line: status}
220-
)
234+
if scope != "line":
235+
# Expand the status to cover all relevant block lines
236+
self._set_state_on_block_lines(
237+
self._msgs_store, self._module, msg, {line: status}
238+
)
239+
else:
240+
self._set_message_state_on_line(msg, line, status, line)
221241

222242
# Store the raw value
223243
try:

tests/functional/d/disable_msg_next_line.py

+7
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,10 @@ def function_C():
1818

1919
def function_D(arg1, arg2): # [unused-argument, invalid-name]
2020
return arg1
21+
22+
23+
def function_E(): # [invalid-name]
24+
# pylint: disable-next=unused-variable
25+
26+
test = 43 # [unused-variable]
27+
blah = 123 # [unused-variable]

tests/functional/d/disable_msg_next_line.txt

+3
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,6 @@ unused-variable:15:4:15:5:function_C:Unused variable 'x':UNDEFINED
33
f-string-without-interpolation:16:11:16:44:function_C:Using an f-string that does not have any interpolated variables:UNDEFINED
44
invalid-name:19:0:19:14:function_D:"Function name ""function_D"" doesn't conform to snake_case naming style":HIGH
55
unused-argument:19:21:19:25:function_D:Unused argument 'arg2':HIGH
6+
invalid-name:23:0:23:14:function_E:"Function name ""function_E"" doesn't conform to snake_case naming style":HIGH
7+
unused-variable:26:4:26:8:function_E:Unused variable 'test':UNDEFINED
8+
unused-variable:27:4:27:8:function_E:Unused variable 'blah':UNDEFINED

0 commit comments

Comments
 (0)